一、HashMap底层原理
简述
HashMap是Java开发过程中使用最多的集合之一,其中的put(key,value)和get(key)方法,是我们在使用HashMap时最常使用的方法,但是底层的原理我们可能就了解得比较少了,或许你知道HashMap是使用hash算法,然后基于数组+链表+红黑树来实现的,或许还知道HashMap内部数组的初始长度为16,并且还能自动扩容.今天我们就来探究一下put(key,value)和get(key)这两个常用的方法的实现过程和原理.
-
put(key,value)的原理
首先我们调用put方法的时候,方法内部会调用hash(key)方法,计算出key的hash值,
然后通过HashMap的主干部分(数组tab)的长度length来进行位与运算(length-1)&hash得出一个index=(length-1)&hash值,然后直接根据index的值,将Node对象放入对应的tab[index]=Node即可,如下面伪代码和图所示:
HashMap mapDemo=new HashMap()
mapDemo.put("name","Aiden")时,
Node node=new Node("name","Aiden");
int index=hash("name")&length-1,假如算出index=2
tab[2]=node;
虽然在计算index的时候采用的是均匀分布算法,但是当put的key-value越来越多时,不可避免的会出现计算的index出现重复,这个时候就需要用到链表结构了,其实我们的Node对象不仅仅是数组里面的一个元素,还是可能是一个链表的头节点,通过next指向链表的下一个Node对象节点.当出现重复index的时候则以下面的方式进行插入:
mapDemo.put("name","Aiden")时,
Node node3=new Node("galary","1K");
int index=hash("galary")&length-1
假如算出index=3,发现数组里面里面index=3的位置已经有Node对象node2了
这个时候就转换成链表结构原来的Node对象成为链表的头节点,
新put的Node对象,插入依次链表的尾部("尾插法")(jdk1.8之前是用头插法,jdk1.8采用尾插法),如图:
另外当链表的长度达到一定值(默认为8)之后,会转换成红黑树的结构,如下图:
-
get(key)的原理
一般情况下,首先根据k