equels和hashCode

前言

java的基类Object提供了equals和hashCode方法,前者判断两个对象是否相等,后者用于计算对象的哈希码

equals

object类中equals中是这样写的

public boolean equals(Object obj) {
    return (this == obj);
}

该实现采用了 区分度最高的算法,只要两个对象不是同一个对象就返回false

equals方法可以重写,但是要遵守约定

hashCode

object类中hashCode中是这样写的

public native int hashCode();

可以看出是本地方法,实际上是将该对象在内存中的地址作为哈希码返回,可以保证不同对象哈希码不一样

hashCode重写也有注意事项

hashMap和hashSet的实现也是遵循上面的规则的,当哈希表中插入对象时,通过获取对象哈希码直接定位,如果该位置没有对象,则将对象插入到该位置,如果该位置已经有对象,则通过equals判断是否是同一个对象,如果是则不插入,如果不是则将对象加入到链表中

integer中的equals和hashCode

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}
public static int hashCode(int value) {
    return value;
}

String中的equals和hashCode

public boolean equals(Object var1) {
    if (this == var1) {
        return true;
    } else {
        if (var1 instanceof String) {
            String var2 = (String)var1;
            int var3 = this.value.length;
            if (var3 == var2.value.length) {
                char[] var4 = this.value;
                char[] var5 = var2.value;

                for(int var6 = 0; var3-- != 0; ++var6) {
                    if (var4[var6] != var5[var6]) {
                        return false;
                    }
                }

                return true;
            }
        }

        return false;
    }
}

public int hashCode() {
    int var1 = this.hash;
    if (var1 == 0 && this.value.length > 0) {
        char[] var2 = this.value;

        for(int var3 = 0; var3 < this.value.length; ++var3) {
            var1 = 31 * var1 + var2[var3];
        }

        this.hash = var1;
    }

    return var1;
}

通过代码可以看出

  1. 使用质数计算哈希码,由于特性,与其他数字相乘后结果唯一概率更大,哈希冲突概率更小
  2. 质数越大,哈希冲突概率越小,但是运算速度越慢,选择31是实践后择中的选择
  3. 我们都知道位运算快于其他运算,jvm会对31进行优化 31 * i == (i « 5) - i