【问题标题】:String.equals implementationString.equals 实现
【发布时间】:2016-02-07 15:32:12
【问题描述】:

在 JDK 8 中,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;
}

为什么迭代使用两个操作 - 递增 i 和递减 n 而不是类似的操作:

while (i < n) {
    if (v1[i] != v2[i])
        return false;
    i++;
}

while (i-- != 0) {
    if (v1[i] != v2[i])
        return false;
}

进行一次递增或递减操作?

我想,它在某种程度上与 JVM 字节码优化有关,但不明白如何。

【问题讨论】:

  • @Thilo 你是对的。错过了这一点。
  • 如果这是某种巧妙的优化(看不出如何),这是他们决定不用于Arrays.equals 的优化。 Arrays.equals 只是使用了明显的 for 循环。
  • 事实上,String.equals 可以在这里调用Arrays.equals。可能出于性能原因没有完成(调用开销?)。

标签: java string equals


【解决方案1】:

实际上,这个 java 代码与真实机器代码没有直接关系(至少对于现代桌面/服务器 JVM)。您可以阅读“HotSpot VM 中的内在方法”。例如。 When will JVM use intrinsics

【讨论】:

    【解决方案2】:

    我认为这是死代码,是从 Strings 仍然共享支持数组并具有 offsetcount 的时代遗留下来的,因此您需要稍微调整索引。

    在 JDK 7 Update 6 中更改了 String 实现(很多人对此感到不安,尤其是它发生在一个小版本中)。字符串不再共享支持数组(除非字符串本身相等,在这种情况下,新的重复数据删除器会尝试重新共享它们)。

    您可以在“how does String.equals() work”上查看有关旧实现的讨论。

    【讨论】:

    • 另一个有趣的方面是equals不使用字符串的hashCode。这在stackoverflow.com/questions/14262431/… 进行了讨论
    • 现在数组不再共享,还可以比较两个数组的对象身份 (if (value == anotherString.value) return true)。我想这不会发生太多。
    • 他们在比较字符串的身份时不是已经这样做了吗?
    • @PaulBoddington: 否。new String("a") != new String("a")(但它们可能具有相同的后备数组,即使在 JDK8 中也是如此)
    • 谢谢。我不知道,我以为现在所有的字符串都有自己的数组了。
    猜你喜欢
    • 2014-08-18
    • 2020-10-30
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2014-04-18
    • 2021-09-04
    相关资源
    最近更新 更多