从解析String的hashCode和equals方法源码到hash冲突

经常被问到hashcode方法和equals方法还有== ,网上都有结论,但我们不能知其然却不知其所以然。所以我们从string的hashcode和equals入手,探究这3者,先贴源码。

 public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
hashcode
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;
    }
equals

1.string的hashcode主要代码  h = 31 * h + val[i];

遍历所有字符,val[i]对应ASCII表中的值,将它与h*31累加。最终得出一个hash值,但我们可以从这个算法得知,不同的字符串有可能得出相同的hashcode值(概率很低)

比如2个val1[1,0];val2[31]; 我这里直接将ASCII值代替进去了,它们运算后的h都是31,但它们代表的内容不同。

所以通过hashcode值判断2个字符串是否相等是不行的。

2.equals方法.

  == : 它的作用是判断两个对象的地址是不是相等

  equals方法先判断2个字符串==,假如2个字符串都==了,就是同一个对象了,肯定就相等了。

  然后遍历2个字符串,一一对应比较字符,假如都相等了,就说这2个字符串内容一样。

 

总结:equals方法比较了2个字符串是否是同一个对象,并且比较它们的内容是否一样。

    如果是同一个对象那么内容肯定一致,根据hashcode算法它们的hash值也一样,

    不同对象,它们内容也可能一致,内容一致hash值也就一样,

    但是内容和对象都不一样,它们的hash值有可能相同,这样就出现了所谓的hash冲突。原因取决于hashcode的算法(见1)

所以通过hash值来比较2个字符串内容是否一致严格上是错误的。

 

posted @ 2018-11-30 04:49  sagan15  阅读(710)  评论(0编辑  收藏  举报