Class Person
String name
int age
Person p1 = new Person("a", 42);
Person p2 = new Person("b", 11);
因为String的hashCode函数是以字符的ASCII码为基础计算的,元素的hash值是所有属性hash值的和,得出p1和p2的hash值相同则称为哈希冲突。a的ASCII值是97,b的是98,计算出p1和p2hash值都是3049。
同一个索引上的多个元素以链表的方式共存。
String的hashCode()
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()
@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; }
了解为什么hashCode计算中频繁使用31:?
以Eclipse/IDEA为例,在自定义类中可以调用工具自动重写equals和hashCode。
问题: 为什么用Eclipse/IDEA复写hashCode方法,有31这个数字?
1. 选择系数的时候要选择尽量大的系数。因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。(减少冲突)
2. 并且31只占用5bits,相乘造成数据溢出的概率较小。
3. 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化。 (提高算法效率)
4. 31是一个素数,素数作用就是如果我用一个数字来乘以这个素数,那么最终出来的结果只能被素数本身和被乘数还有1来整除! (减少冲突)