我们都知道java所有的类都是java.lang.Object的子类,而Object的hashCode方法和equals方法是native方法,依据父类的方法调用equals方法比较的是两个对象的物理地址空间。
而再大的空间(依旧有限大小)在进行分配及占用时,依旧会存在hash碰撞,即我们所知道的对象不一而初次计算的hash值一样(可以参照hashMap理解)。这里重审一下,对于两个equals(Object)返回为true的对象,其hashCode一定是相同的,反之则不一定。
为了缓解哈希碰撞,解决方案从尽量打散,多次重算哈希值出发。但无论怎么去设计和重写,要遵循以下:
·同一个对象多次调用hashCode()方法应该返回相同的值;
·当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()应该返回相等的(int)值;
·对象中用作equals()方法比较标准的Filed(成员变量(类属性)),都应该用来计算hashCode值。
参照java中的String类对hashCode方法的重写,其hashCode为每个字符的ASCII码值累加hash左移5位减去hash(即hash*31)。使用31这个奇质数,也是为了避免偶数或者合数乘法运算中产生溢出,导致数值信息丢失。
JDK中equals方法注释翻译:
1.在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
3.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。