HashMap
底层是数组+链表+红黑树,集数组和链表的优点与一身,线程不安全。
数组:
在新建一个HashMap时,会初始化一个数组,在JDK1.8之前初始化的数组初始容量为16,但在JDK1.8及之后,它实现了一个懒加载功能,就是在第一次put数据时才会初始化容量,初始容量仍然是16,在添加数据时,添加数据的下标是由key经过hash算法生成的,获取的hash值与数组长度进行一个取余算法获取下标,取余不是用‘%’,而是用‘&’,因为‘&’的运算比‘%’快,而且用数组的长度肯定是2的次幂,所以不用担心‘%’和‘&’这俩个算出的值不相等的问题(只有长度为2的次幂时,‘%’和‘&’的结果才肯定相等)。在容量达到当前容量的0.75倍时,数组会进行扩容,规则是扩容为原来的2倍,比如当前容量为16,当添加第13个数据时,数组就会进行扩容,扩容后所有key重新进行hash算法重新获取自己的‘房子’
链表
在添加数据时,当hash算法算出新key的值与数组中某个key一致时,会触发链表结构,相当于在老key旁边放一个小板凳让新key坐,如图所示
红黑树
当链表的长度大于等于8时会链表会转成红黑树,当它长度再次小于6之后会再转为链表,否则仍以红黑树存储数据,在这里有个重点,就是当数组的长度小于64时,链表是不会转为红黑树的,因为当数组长度小于64,使用数组加链表比使用红黑树查询速度要更快、效率要更高。