Map的实现类 (HashMap 底层实现是数组加链表加红黑树)
1. HashMap使用Node数组来保存数据 Node实现了Map.Entry接口
2. HashMap如果数据量达到了阈值会触发扩容机制 阈值=数组容量*加载因子 (数组容量默认是 16 加载因子默认是0.75)
3.通过hash&(tab.length-1) 来确定元素在Node数组中的位置 每个位置可以有多个元素通过链表的形式来连接 当链表的中元素的数量大于要转换为红黑树的阈值(默认是8)时 会把链表转换为红黑树
4.链表转红黑树的步骤 (1).将链表的元素转换为TreeNode(比普通的Node多了了一些元素 parent left righ redt等) (2).把TreeNode插入到根据hash值构建的二叉排序树中 (3).每插入一个TreeNode 就重新调整为一颗红黑树 (4).TreeNode=TreeNode.next 重复执行2和3操作 直到所有的TreeNode都插入完毕
5.操作为非线程安全
6.key和value都可以为null 取hash值的时候 如果key为null hash=0
HashMap的扩容规则
1.触发扩容的规则是 数组元素的数量>数组容量*加载因子
2.如果Node数组没有被初始化过 (如果初始化没有设置初始容量 则为默认容量16 否则设置为>=初始容量的2的最小次幂) 己经被初始化过(扩展为原容量的2倍)
3.扩容完成以后 则进行HashMap的重新hash规则
HashMap的重新hash步骤
1.针对原Node数组的一个位置首先判断是否只有一个节点 只有一个节点直接重新计算位置 有多个节点则步骤2
2.首先判断现在是一颗红黑树还是一个链表 红黑树进入3 链表进入4
3.把重新hash完之后留在原位置的和新位置(原位置+原数组容量)的分为两个链表 判断每个链表的元素数量 如果小于转为红黑树的阈值 就把TreeNode重新转换为Node节点 如果大于重新转换为一颗红黑树
把链表或者红黑树设置到对应的位置上
4.把重新hash完之后留在原位置的和新位置(原位置+原数组容量)的分为两个链表 把链表设置到对应的位置上
5.重复执行以上步骤 直到原数组的所有位置全部被重新计算过
红黑树的一些基本的规则
1.红黑树是一个二叉排序树。
2. 根节点一定是黑色。
3. 不能有两个红色的节点相邻。
4. 节点不是红色就是黑色。
5.每个叶子节点都是黑色的空节点(NIL节点)。
6.从任意节点到其每个叶子的所有路径都包含相同数目的黑色节点。
7.新插入的节点一定是红色。
红黑树的变换规则(x是指当前节点)
1.颜色变换
条件
x.color==red
x.parent.parent.left.color==red
x.parent.parent.right.color==red
操作
x.parent.parent.left.color==black
x.parent.parent.right.color==black
x.parent.parent.color=red
x=x.parent.parent(重新判断x节点是否满足红黑树)
2.左旋 (LR)
条件
x.parent.rignt==x
x.parent.parent.left==x.parent
x.color==red
x.parent.color==red
x.parent.parent.right.color==(null || black)
操作
以x.parent为支柱 向左旋转
旋转之后 以之前的x.parent当做x 重新判断x节点是否满足红黑树
3.右旋 RL
条件
x.parent.parent.right==x.parent
x.parent.left==x
x.color==red
x.parent.color==red
x.parent.parent.left.color==(null || black)
操作
以x.parent为支柱 向右旋转
旋转之后 以之前的x.parent当做x 重新判断x节点是否满足红黑树
4.右旋LL
条件
x.parent.parent.left==x.parent
x.parent.left==x
x.color==red
x.parent.color==red
x.parent.parent.right==null or color== black
操作
x.parent.color=black
x.parent.parent.color=red
以x.parent.parent为支柱 向右旋转
5.左旋 RR
条件
x.parent.parent.right==x.parent
x.parent.right==x
x.color==red
x.parent.color==red
x.parent.parent.left==null or color== black
操作
x.parent.color=black
x.parent.parent.color=red
以x.parent.parent为支柱 向左旋转
Map的实现类 (HashTable 底层实现是数组加链表)
1. HashTable使用Entry数组来保存数据 Entry实现了Map.Entry接口
2. HashTable如果数据量达到了阈值会触发扩容机制 阈值=数组容量*加载因子 (数组容量默认是 11 加载因子默认是0.75)
3.通过 (hash & 0x7FFFFFFF) % tab.length 来确定元素在Entry数组中的位置 每个位置可以有多个元素通过链表的形式来连接 每次插入在链表的头部
4.操作为线程安全
5.key和value都不能为空 hash=key.hashCode()
HashTable的扩容规则
1.触发扩容的规则是 数组元素的数量>=数组容量*加载因子
2.扩展为原数组容量的2倍+1
3.扩容完成以后 则进行HashTable的重新hash规则(对所有元素重新计算位置)
Map->SortMap的实现类 (TreeMap 底层实现是红黑树)
1.使用Entry来保存根节点类似于HashMap的TreeNode节点
2.非线程安全
3.通过传入的Campator比较器 或者是实现了Compareable接口的对象来比较大小
5.value可以为空 当camparator==null时 key不能为空 否则可以为null
ConcurrentHashMap