hashmap的1.7的底层架构
从jdk1.6和jdk1.7开始,hashmap的底层结构是数组加链表实现的 .将key的hash值进行取模获取index 既即将存放的元素的数组的位置.然后到对应的链表中进行put和get操作.
这里说明下为什么要加上链表.因为对数组进行取模的时候可能会遇到获取index的位置是一样的,所以可能会遇到hash碰撞冲突.此时
为了将元素存放进去,采用链表的方式进行存储数据,既在同一个index位置加了一个链表,该链表存放了若干个key的hash值取模后的index值一样的元素.然后在put和get的时候也通过取模获取index ,然后获取链表,再对链表进行遍历获取到链表中的某一个key值和原始的key值相同,则返回该值(这样不好,效率不高,每次都得遍历.时间复杂度为o(n),所以jdk1.8做了优化,下面会说.)
链表的原理
下面新建一个测试节点 第一次new一个链表, 然后next属性为空. 然后在加入新的节点的时候 将链表第一个节点既头结点的next属性指向新节点的对象.
header.next = new Node(new Object() ,null);
如果此时又加入一个节点.想将新的节点加在链表的头部,此时需要将新节点的next属性设置为原先头结点的对象然后赋值给头节点原先的对象.这样始终就保持头结点就是最新插入的数据.
jdk1.7 头插法.
Put的方法里面的这行代码table[index] = new Entry(key,value,table[index]); 就是上面头插法的一个方式
既在new一个entry节点的时候将老节点作为新节点的下一个节点.然后赋值给新节点.始终保证头结点的数据是新插入的数据.
观察hashmap源码的put方法 thresold 就是传入数组的长度.不传的时候默认是16.
会发现当table为空的时候调用了inflateTable方法对map进行了初始化. roundUpToPowerOf2(toSize) 方法就是获取比size大的2的n次方的数返回. 既tosize为10