一、HashMap的底层原理
在JDK7.0
1.HashMap底层是使用数组加链表的方式存储数据。
2.在存储数据时会根据哈希值进行运算,获得0到length-1的索引,将数据存储在指定的数组中,若数组中已存在元素,就会判断是否重复,若无重复,会取出原来的元素,将新元素添加到数组中,并用next指向原来的元素。
3.加载因子(loadFactor)是判断HashMap是否扩容的标识。
4.如果元素个数>= (length / loadFactor)且添加所在的数组不为null时数组的长度就会扩充一倍。
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
5.使用有参构造方法设置初始容量时,若length不是 2n,length会向上转换成2n。
roundUpToPowerOf2(int number) 方法中 number为有参构造初始容量, MAXIMUM_CAPACITY为数组的最大容量
private static int roundUpToPowerOf2(int number) {
// assert number >= 0 : "number must be non-negative";
return number >= MAXIMUM_CAPACITY
? MAXIMUM_CAPACITY
: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}
public static int highestOneBit(int i) {
// HD, Figure 3-1
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
return i - (i >>> 1);
}
6.HshMap中加载因子默认为0.75。
7.在HashMap对象使用put()方法时,会判断数组是否为null或长度为0,如何是,就会new一个初始长度为16的数组。
8.put(key,value)方法中key为主键,value为值,一个key对应一个value,key不能重复,若添加的key有重复的,会覆盖key对应的value值。
在JDK8.0
1.当数组length>=64并且链表长度>=8时,会将链表转换成红黑二叉树
2.在使用put()方法添加元素时,会将元素添加到链表的末尾(原有元素next指向新元素),