16

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

我查看了 Open JDK 6 中实习生池的 C++ 实现,在那里我看到了一个简单的HashSet. 对我来说,这意味着当有人尝试实习时,String应该完成以下步骤:

  1. 查找与给定关联的哈希码String
  2. 找到合适的桶
  3. 将给定的字符串与桶中的所有其他字符串进行比较。在此步骤之前,桶中可能有 0 个字符串、一个字符串或很多字符串。因此,如果给定的字符串之前已放入桶中,我们将至少得到一个比较(这是最好的情况。当然可能有很多冲突,现在桶中还有许多其他字符串)
  4. 如果在桶中找到了字符串,那么它应该通过intern()方法返回
  5. 如果在桶中没有找到该字符串,则应将其放入桶中并通过intern()方法返回

所以很多人说那str1.intern() == str2.intern()会比str1.equals(str2).

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

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

在这种情况下str1.intern() == str2.intern(),我们需要进行多少次比较或将字符串放入池中/从池中取出(对,可能是很多比较,它们也是简单的逐字符比较)?

因此,str1.intern() == str2.intern()即使我们使用==比较字符串,我们也会有许多额外的操作,例如前面描述的比较。

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

第一个结果告诉我,str1.intern() == str2.intern()它比str1.equals(str2).

这种行为是由于String.intern()方法是本机的,因此不应每次都对其进行解释,并且String.equals()是 java 方法。

因此,我决定使用-Xcomp选项让 JVM 在启动时编译所有代码。

在那之后等于展示了比实习生更好的速度。

我在 Java 6 和 7 上对其进行了测试。

所以我的问题是你有没有见过在实习提高字符串比较速度时的情况?我是的,怎么可能?

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

4

2 回答 2

7

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

仅当内存中有许多相同字符串的多个副本时,才使用实习字符串(如果有的话)。通过实习字符串,所有这些副本将使用相同的引用。

只有当我拥有数百万个相同字符串的副本时,我才看到实习字符串很有帮助。

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

有关字符串实习的更多详细信息,请参阅此博客文章

于 2014-04-07T15:37:54.910 回答
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() 对任何字符串计算一次,因为它是不变性的,并且相当快
2)找到存储桶是 O(1)
3)将您的字符串与同一个存储桶中的其他字符串进行比较 - 那里也许有几个,但仍然应该比equals()
4) 和 5) 快

并且不要忘记,对于任何字符串,上述操作只需执行一次,一旦它被intern()编辑,结果就会从第一次比较中返回。

于 2014-04-07T16:01:58.303 回答