HashMap主要是由数组和链表组成,它不是线程安全的。
核心点就是put插入数据的过程,get查询数据以及扩容的方式。JDK1.7和1.8的主要区别在于头插和尾插方式的修改,头插容易导致HashMap链表死循环,并且1.8后加入红黑树对性能有提升。
put插入数据流程
往map插入元素的时候,首先通过key 进行hash算法,然后与数组长度-1进行与运算((n - 1) & hash),都是2的次幂所以等同于取模,但位运算的效率更高。找到数组中的位置之后,如果数组中没有元素直接则直接存入,反之则判断key是否相同,key相同就覆盖,否则就会插入链表的尾部,如果链表的长度超过8,则会转换成红黑树,最后判断数组长度是否超过默认长度*负载因子也就是12,超过则进行扩容。
get查询数据
查询数据相对于来说就比较简单了,首先计算出hash值,然后去数组查询,是红黑树则去红黑树查,链表就遍历链表查询就可以了。
resize扩容过程
扩容的过程就是对key重新计算hash,然后把数据拷贝到新的数组。