String.intern()真的提高了性能吗?

时间:2014-04-07 15:32:47

标签: java string string-interning

我做了一些调查,以了解如何在java中实现String.intern()方法。

我从Open JDK 6看了Intern池的C ++实现,在那里我看到了一个简单的HashSet。对我而言,这意味着当有人试图实习String时,应该完成下一步:

  1. 查找与给定String
  2. 关联的哈希码
  3. 找到合适的水桶
  4. 将给定的String与存储桶中的所有其他字符串进行比较。 在此步骤之前,可能有0个字符串,一个字符串或很多字符串 桶中的字符串。所以如果先前给定的String 放入桶中我们将得到至少一个比较(那是 最好的情况。当然可能会发生很多碰撞 现在许多其他字符串都在桶中)
  5. 如果在存储桶中找到了字符串,那么它应该是 由intern()方法
  6. 返回
  7. 如果在存储桶中找不到String,则应将其放入 在桶中并由intern()方法
  8. 返回

    有很多人说str1.intern() == str2.intern()会比str1.equals(str2)更快。

    但我看不出它应该更快的原因。

    正如我在str1.equals(str2)的情况下所看到的,我们总是有两个字符串在String.equals()方法中比较char和char。

    str1.intern() == str2.intern()的情况下,我们需要进行多少次比较或将字符串放入池中(对,它可以进行大量比较,它们也是char比较的简单char) ?

    所以在str1.intern() == str2.intern()的情况下,即使我们使用==比较字符串,我们也会有许多其他操作,例如前面描述的比较。

    当我理解它时,我决定做一些基准测试。

    第一个结果告诉我str1.intern() == str2.intern()str1.equals(str2)快。

    此行为是由String.intern()方法是本机的,因此不应每次都解释而String.equals()是java方法。

    然后我决定使用-Xcomp选项让JVM在start时编译所有代码。

    在那之后等于比实习生更快的速度。

    我在Java 6和7上测试过它。

    所以我的问题是,你有没有看到一种情况,当实习增加字符串比较的速度?我是怎么回事?

    或许intern()只能帮助节省更多可用内存?

2 个答案:

答案 0 :(得分:7)

String.intern()旨在减少内存的使用。

只有在内存中有多个SAME String的多个副本时,才使用interned Strings(如果有的话)。通过实习字符串,所有这些副本将使用相同的参考。

当我有数百万相同字符串的副本时,我只看到实习字符串有用。

与任何类型的优化一样,只有在出现性能或内存问题并且您对其进行了分析后才能检测到这是瓶颈。

See this Blog post了解有关字符串实习的更多详情。

答案 1 :(得分:3)

关于为什么str1.intern() == str2.intern()可能更快的问题:

这是String.equals()实现 - 正如您所看到的,根据比较的字符串,它可能效率非常低。

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

您的步骤可能会快很多:
1)hashCode()由于它的不变性而对任何String计算一次并且相当快 2)找到桶是O(1)
3)将你的字符串与同一个存储桶中的其他字符串进行比较 - 可能有一些但仍然应该比equals()更快 4)和5)快速

并且不要忘记,对于任何字符串,上述操作必须只执行一次,一旦intern()结果从第一次比较返回。< / p>