HashMap的原理
(JDK 1.7)HashMap是由数组+链表的形式实现的,集成了数组的获取元素方便以及链表的插入元素方便的优点,初试数组长度设置的是16位。其中HashCode代表了在hash表中的位置。并且在HashMap中有一个Hash算法 (使用异或运算) 使得链表的位置在数组中尽量均匀分布,来减少 哈希碰撞 的几率。
因为计算方式使用的是位与运算,为了防止链表的位置可能多次出现在数组的第一个位置,尽量将HashMap的长度保持为2的次方数——当然在HashMap中也有相应的处理(tableSizeFor方法)来使得数组长度变成2的次方数。
红黑树的基本概念(JDK1.8之后加入)
- 每个节点是黑色或者是红色;
- 根节点是黑色;
- 每个叶子节点(NIL)是黑色 (这里叶子节点,是指为空的叶子节点);
- 如果一个节点是红色,则它的子节点必须是黑色;
- 从一个节点到节点的子孙节点的所有路径上包含相同数目的黑节点。
出现的问题:性价比----时间和空间复杂度
HashMap扩容机制
HashMap中插入东西的时候的思路:
- 数组 ---- 没元素,直接放;
- key是不是同一个,如果是,替换value;
- key不是同一个,且数组有元素,判断是链表或是树 --> 是链表(是否达到树的要求) 没达到就挂链表,达到了就变成树;链表长度达到==8这个数字的时候,会转成红黑树;
- key不是同一个,且数组有元素,判断是链表或是树 --> 是红黑树,挂到红黑树后面的节点去;
- 当数组被使用的长度达到数组原始长度的四分之三之后,会开始进行扩容机制,数组长度会翻倍。
- 这时候,会建立一个新的长度为原长度两倍的数组,然后遍历原数组:
- 如果只有一个元素,就直接取模搬过来
- 如果数组下是一个链表,就遍历链表之后取模复制过来
- 如果是一个树,每个节点再计算一次hash,然后把树打散,一个元素一个元素去拿;
@SuppressWarnings({
"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node