HashMap在1.8和1.8之前的变化
1. JDK1.8之前
HashMap底层是使用数组和链表结合在一起使用,即链表散列。HashMap通过key的HashCode经过扰动函数hash(int h)处理后得到hash值,然后通过((n-1)& hash)确定该元素存放的位置,if 当前位置已存在元素,就判断当前位置的元素hash值以及key 是否相同,如果相同则直接覆盖,不相同就通过拉链法解决冲突。
jdk1.8 扰动函数hash(Object key)的源码:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//通过右移16位使得高16位也参与进来,降低hash冲突
}
jdk1.7 扰动函数hash(int h)的源码:
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
1.7扰动函数经过了4次处理,性能会略差于1.8
数据结构简图1.8之前:
2.JDK1.8之后
解决hash冲突时有了较大变化,当链表长度大于阈值(默认为8),并且数组长度大于64时会将链表转换为红黑树,以减少搜索时间,如果数组长度小于64时会先进行数组扩容(resize())