为什么String中的equals方法不使用哈希?

Mar*_*llo 44 java string hashcode

equalsString类中方法的代码是

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
            return true;
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

我有一个问题 - 为什么这个方法不使用hashCode()?

据我所知,hashCode()可以快速比较两个字符串.

更新:我知道,两个不相等的字符串,可以有相同的哈希值.但两个相等的字符串具有相等的哈希值.因此,通过使用hashCode(),我们可以立即看到两个字符串是不相等的.

我只是想,使用hashCode()方法可以很好的过滤器equals.

更新2:这里有一些代码,我们在这里谈论.

这是String方法等于的示例

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        if (hashCode() == anotherString.hashCode()){
            int n = count;
            if (n == anotherString.count) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;
            }
        }else{
            return false;
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

par*_*fal 39

Hashcode可能是对不平等的第一轮检查.但是,它提出了一些权衡.

  1. String哈希码是懒惰计算的,尽管它们使用"保护"值.如果你要比较长寿命的字符串(即,他们可能已经计算了哈希码),这不是问题.否则,您将无法计算哈希码(可能很昂贵)或者在尚未计算哈希码时忽略检查.如果你有很多短命的字符串,你会比你使用它更频繁地忽略支票.
  2. 在现实世界中,大多数字符串的前几个字符都不同,因此首先检查哈希码不会节省太多.当然,有例外(例如URL),但在现实世界的编程中,它们很少发生.

  • @ssg - 不,这是一种认识,没有绝对的,设计的一部分是找出常见的情况并对其进行优化.当然,如果您针对不常见的情况进行优化,那么您必须遵守决策的必然结果.初学者应该尽早学习. (6认同)
  • "在现实世界中,大多数字符串的前几个字符都不同,因此首先检查hashcode不会节省太多." 这只是一个狡猾的词,它可能会让初学者感到困惑.http://en.wikipedia.org/wiki/Weasel_word (3认同)
  • 这听起来像是你提出个人意见.你对答案中常见内容的断言与你的评论相矛盾,这些评论指出"人们应该找出他们自己的常见案例". (2认同)
  • @parsifal:你在答案中的陈述听起来并不像你根据实施决定所假设的事实.听起来你有一个科学的,经过验证的事实,它普遍适用于所有事物.这是黄鼠狼的一部分.我说它对初学者来说是误导.有这样的捷径结论是危险的.我以为你是建议初学者去研究,但你说你没有这么说.所以现在它甚至是一个更危险的声明. (2认同)

ass*_*ias 14

这个问题实际上已经被JDK的开发人员考虑过了.我在各种消息中找不到为什么它没有被包括在内.增强功能也列在错误数据库中.

即,建议的变更之一是:

public boolean equals(Object anObject) {
    if (this == anObject) // 1st check identitiy
        return true;
    if (anObject instanceof String) { // 2nd check type
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) { // 3rd check lengths
            if (n != 0) { // 4th avoid loading registers from members if length == 0
                int h1 = hash, h2 = anotherString.hash;
                if (h1 != 0 && h2 != 0 && h1 != h2) // 5th check the hashes
                    return false;
Run Code Online (Sandbox Code Playgroud)

还有一个讨论==用于实习字符串(即两个字符串是否被实习:) if (this != anotherString) return false;.

  • @MaryRyllo添加了bug数据库的链接. (2认同)

MrS*_*h42 7

1)计算hashCode可能不比直接比较Strings快.

2)如果hashCode相等,则字符串可能仍然不相等

  • hashcode仅针对一个字符串计算一次. (4认同)