2021.2.10随笔
HashMap(重点!!!背下来)
(这块别问,直接全部背下来就对了)
(1) hashmap 的底层结构 : 数组 + 链表 + 红黑树 (jdk 1.8)
(jdk1.8之前: 没有红黑树, 就是数组 + 单链表)
(2)hashmap 底层维护了一个数组
(3)数组默认初始容量 16 , 数组扩容机制: 扩为原来的 2 倍, 默认的加载因子是 0.75
(4)无序
(5)不允许重复的 key: p.hash = key.hash && ( p.key == key || p.key.equals(key))
(6)允许存储 null 键,: 下标:0
(7)线程不安全
(8)Hashmap 能存储的元素数量 < = 底层数组长度 * 加载因子的
(9)hashmap 怎么判断重复的问题:
// (hash是否一样 && (key 直接相等 || key 相 equals ))
Hash = (h = key.hashCode()) ^ (h >>> 16)
(10)如果在创建 hashmap 的时候, 我们给定长度, 那么 hashmap 会根据我们给定的长度, 计算一个大于等于该长度的最小的2的幂值, 用来充当底层数组的长度
(11) 加载因子(如果要改变,尽量保证0.5 ~ 1. (习惯) 0.75 )
(12)当数组的某一个位置, 存储元素的过多, 有可能导致链表转化为红黑树
界定条件: 8
先产生链表, 当链表过长的时候, 链表转化为红黑树
**链表超过 8 达到 9 (包含新添加的元素) 的时候, 会把链表转化为红黑树**
(13)红黑树 --> 链表
A, 删除: 红黑树 ---> 链表
树的根节点, 根节点左右结点, 根节点的左节点的左节点, 只要这四个结点, 有一个是null, 那么就会由红黑树, 转化为链表
B, 扩容
扩容的时候, 树会分列成两部分(新位置, 旧位置), 有可能导致, 被分列的树过小, 就需要由红黑树转化为链表, 以节省内存.
经过分列的树的元素个数 <= 6 : 就会由红黑树 转化为链表
(14)如果链表长度超过8达到9时候, 一定会有链表转化为红黑树吗?
不一定, 如果当数组长度小于64的时候, 是会优先扩容, 而不是转化为红黑树
如果数组长度超过64, 必定由链表转化为红黑树
(15)如果已经添加到 hashmap 中的元素( key-value 的 key), 不要通过引用去修改它
补充
(1)为什么要求hashmapd的底层数组长度是2的幂值?
在扩容之后重新散列, 会让一个原本存在于原数组x位置的元素, 仅散列到两个位置(x , 原本len + x)----(对红黑树/非单元素链表, 重新散列有好处)
// 数组-->扩容
// key-value 数据: key—计算--> hash值 ----取余-->下标 --> 比较是否重复/存储
(2)
// 1, "zs" --计算 ---> hash值
// 2, 根据 hash ----取余 --- 计算数组下标
// 3, 找到这个数组下标, 查找可"zs"这个key相同的值
// key.hash == p.hash && ( key == p.key || key.equals(p.key))
// 4, 如果相等了, 返回p.value
LinkedHashMap(记忆)
1, LinkedHashMap 是 HashMap 的子类
2, LinkedHashMap, 底层机构(数组+链表+红黑树)以及基本特点都遵从于 HashMap
(基本特点和 HashMap 基本一模一样)
3, LinkedHashMap 是有序的: 他的底层结构,在 HashMap 基础上, 又额外维护了一个双向链表 --> 进一步使 LinkedHashMap 有序
TreeMap(记忆)
1, 他是Map的一个树(红黑树)实现
2, 底层结构是红黑树
3, 大小有序.
4, 不能存储’’重复’’元素 key ----自然顺序的重复
5, 不允许存储null-- key
6, 线程不安全
7, 如果使用默认的构造方法(什么参数都不传), 要求存储的元素的 key, 应该实现 ‘自然顺序’
8, 如果在 TreeMap 中存储的元素, 没有实现 “自然顺序”, 那么 TreeMap 如果提供了比较器也是可以比较的
9, 如果比较器和自然顺序同时存在, 优先使用比较器
红黑树 --> 二叉搜索树----重复---- 自然顺序
Set(记忆)
Set是collection集合子接口
1, 不允许重复:
HashSet, LinkedHashSet, 重复 --> HasMap 和 LinkedHashMap key的重复
TreeSet --> TreeMap —> 自然顺序重复
2, 有些子实现是可以存储 null, 有些子实现不可以存储 null
3, 有些子实现是有序的, 有些子实现是无序的
HashSet
1, 底层持有了一个 HashMap 对象 , 近似的认为( HashSet 的底层机构是: 数组 +链表+ 红黑树)
2, 初始长度, 扩容机制, 加载因子的特点都遵从于 HashMap
3, HashSet 存储元素的特点, 完全上遵照 HashMap 的 key 的特点
4, 线程不安全
LinkedHashSet
1, 底层持有的是一个 LinkedHashMap 对象( LinkedHashMap 又是基本复用了HashMap 的底层结构, 只不过多加了一个双向链表)
2, LinkedHashSet : 有序(底层的 LinkedHashMap 有一个双向链表)
3, ListedHashSet : 他的基本特点遵从于 LinkedHashMap 的 key 的特点, 基本遵从于 HashMapdkey 的特点
4, 有序, 允许 null , 不允许重复
TreeSet
1, 底层持有了一个 TreeMap 对象(底层是 红黑树)
2, 存储的元素, 要求实现自然顺序, 如果存储的元素没有实现自然顺序, 那么 TreeSet 要提供比较器
3, 他不允许存储 null (没办法比较大小)
4, 大小有序
5, 不能存储重复元素( 自然顺序比较结果 或者 比较器比较结果, 认为重复的数据)
6, 如果已经存储到 TreeSet ( HashSet, LinkedhashSet )中的元素, 不要通过引用修改它
7, 线程不安全