HashMap底层原理—个人理解 需再深入
jdk1.7
底层的数据结构是 数组+ 链表
put 存值和取值 entry对象
根据 entry对象利用hash算法 算出该hash值.然后再取余,可以得到该对象再数组的位置,(k,v,hash,指针)
因为不同的值 利用hash算法 得到的hash值是永远是一致的.所以这个时候不同的值就会在数组的同一位置,就会覆盖之前的值.这就产生的了 hash碰撞(hash冲突) ,这是可以用链表来.解决hash碰撞的问题.
当增加数据是,采用的是头插法,就是当有新数据 插入进来,就直接放在原数据的上面,然后链表整体下移一位.
这是如果这个链表过长,根据链表的数据结构特性.查询慢.那么查询起来就非常耗费时间.时间复杂度就是O的n次方
先插入,在扩容
jdk1.8
数组 +链表+红黑树
由于链表查询慢,这时就采用了红黑树,是最均衡的,put和get方法都比较均衡.
采用尾插法是因为为了避免出现逆序且链表死循环的问题(JDK1.7的HashMap扩容导致死循环了解哈 cpu100% 内存溢出)。
红黑树的转换也是阈值的,当链表的节点是8 时 就进入转换为红黑树的方法,里面还需要进行一个判断数组长度是都<=64,如果小于,就转换成红黑树,如果>64 那么就先进行数组的扩容.然后再重新计算.
先扩容,再插入
如果是红黑树转化为链表 阈值是6 .如果是红黑树 节点小于8 了,也不会立刻转化成链表.只有当节点等于6时.才会转换成链表.这也是为了避免 以8作为临界值,频繁的转换.