谈一下HashMap的底层原理是什么?
jdk1.7前采用数组+链表结构,jdk8后采用数组+链表+红黑树的数据结构.我们通过put和get存储和获取对象.当我们给put方法传递键和值时,先对键进行hashcode()的计算来得到它在bucket数组中的位置来存储Entry对象.当获取对象时,通过get获取到bucket的位置,在通过键对象的equals()方法找到正确的键值对,然后再返回值对象
谈一下HashMap中put是如何实现的?
1.根据key的算出hashcode值
2.如果散列表为空时,调用resize()初始化散列表
3.如果没有发生碰撞,直接添加元素到散列表中去
4.如果发生了碰撞(hashcode值相同),进行三种判断
4.1若key地址相同或者equals后内容相同,则替换旧值
4.2如果不相等且是红黑数结构,就调用树的插入方法
4.3是链表结构,循环遍历直到链表中的某个节点为空,尾插法进行插入,插入之后判断表个数是否到达红黑树的阙值8;也可以遍历到有节点与插入元素的哈希值和内容相同,进行覆盖
5.如果HashMap容量大于阈值,则resize进行扩容
谈一下HashMap中什么时候需要进行扩容,扩容resize()又是如何实现的
扩容场景:
1.初始化数组table
2.当数组table的size达到阈值时 即size>load factor*capacity时,也是在putVal函数中
扩容实现过程:
1.通过判断旧数组的容量是否大于0来判断数组是否初始化过
(1)否的话进行初始化
初始化判断是否调用无参构造器
调用:使用默认的大小和阈值
不调:使用构造函数中初始化的容量,这个容量是经过tableSizeFor计算后的2的次幂