一. Object.hashCode通用约定
1. 在应用程序执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数. 在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致
2. 如果两个对象根据equals(Object)方法比较是想等的,那么调用两个对象总任意一个对象的hashCode方法都必须产生同样的整数结果
3. 如果两个对象根据equals(Object)方法比较是不想等的,那么调用这两个对象中的任意一个对象的hashCOde方法,则不一定要产生不同的整数结果. 但是程序员应该知道,给不同的对象产生截然不同的整数结果,有可能提高hash table 的性能
二. 不覆盖hashCode的错误
由第一部分知,没有覆盖hashCode违反了第二条约定: 想等对象必须具有想等的hashCode,两个对象逻辑上相等,但根据Object的Hash方法,他们是不同的,这样达不到第二条的额效果
三.实现hash方法时,减少冲突的解决方式
一个好的hash算法的理想结果应该是: 为不同的对象产生不相等的hash code,使不相等的实例均匀地分布到所有可能的hash code中:
1. 把某个非零的常数值保存到名为result的int类型的变量中.
2. 对于对象中的每个关键域f(equals方法中涉及的每个域),完成以下步骤:
A. 为该域计算int类型的hash code C
a. 该域是boolean类型 计算(f?1:0)
b. 该域是byte、char、short、int类型 计算(int)f
c. 该域是long类型 计算(int)(f^(f>>>32))
d. 该域是float类型 计算Float.floatToIntBits(f)
e. 该域是double类型 计算Double.doubleToLongBits(f),然后按步骤c计算
f. 如果该域是一个对象的引用,并且该类的equals方法通过递归地调用equals的方式来比较这个域,则同样为这个域递 归地调用hashCode。
g. 如果该域是一个数组,则要把每个元素当做单独的域来处理。也就是说,递归地应用上述规则,对每个重要的元素计算一个散列码,然后根据步骤3中的做法把这些散列值组合起来。如果数组域中的每个元素都很重要,可以利用发行版本1.5中增加的其中一个Arrays.hashCode方法
B. 按照下列公式,把步骤2.a中计算结果hash code C合并到result中:
result = 31* result + c;
3. 返回result
4. 测试
四: 不要试图从hash code计算中排除掉一个对象的关键部分来提高性能
这么做可能导致hash table完全无法使用,在忽略的区域,实例之间的区别依然很大,可能会造成比较大的hash冲突,甚至退化成链表.