HashMap 底层维护了一个名字为table,默认长度为16,负载因子为0.75的数组 。

怎么存

根据元素的哈希值跟数组的长度(table.length - 1 & hash)计算出应存入的位置

判断当前位置是否为null,是直接存入

不是null,表示有元素,调用equals方法比较属性值

一样不存,不一样,存入数组,形成链表

  • jdk8以前:使用头插法,新元素存入数组,老元素挂在新元素下面
  • jdb8:使用尾插法,直接挂在老元素下面,如果同一个下标的链表节点超过8个且数组长度大于等于64,就会转成红黑树,查找速度从O(n)->O(logn)。

扩容机制

HashMap的扩容由 负载因子 控制,默认为0.75,当元素数据超过时 初始容量 x 0.75 触发扩容。比如初始容量为16,阈值就是12,存第13个元素时就会扩容,把数组大小翻倍,然后把所有数据重新计算位置放到新数字里。

HashMap内部结构(数组 + 链表 + 红黑树)


注意HashMap是非线程安全的,多线程环境下可能出问题,比如数据覆盖或者死循环,这时候应该用
ConcurrentHashMap。