关于自然排序与定制排序:
- 自然排序:要求 key 必须实现 Comparable 接口 。
TreeMap<Integer, String> treeMap = new TreeMap<>;treeMap.put(2, "TWO");treeMap.put(1, "ONE");System.out.print(treeMap);// {1=ONE, 2=TWO}
- 定制排序:在初始化 TreeMap 时传入新的 Comparator,不要求 key
实现 Comparable 接口
TreeMap<Integer, String> treeMap = new TreeMap<>((o1, o2) -> Integer.compare(o2, o1));treeMap.put(1, "ONE");treeMap.put(2, "TWO");treeMap.put(4, "FOUR");treeMap.put(3, "THREE");System.out.println(treeMap);// {4=FOUR, 3=THREE, 2=TWO, 1=ONE}
通过传入新的 Comparator 比较器,可以覆盖默认的排序规则,上面的代码按照key降序排序,在实际应用中还可以按照其它规则自定义排序 。
compare 方法的返回值有三种,分别是:0,-1,+1
(1)如果返回0,代表两个元素相等,不需要调换顺序
(2)如果返回+1,代表前面的元素需要与后面的元素调换位置
(3)如果返回-1,代表前面的元素不需要与后面的元素调换位置
而何时返回+1和-1,则由我们自己去定义,JDK默认是按照自然排序,而我们可以根据key的不同去定义降序还是升序排序 。
关于 TreeMap 主要介绍了两点:
- 它底层是由红黑树这种数据结构实现的,所以操作的时间复杂度恒为O(logN)
- TreeMap 可以对 key 进行自然排序或者自定义排序,自定义排序时需要传入 Comparator,而自然排序要求key实现了 Comparable 接口
- TreeMap 不是线程安全的 。
WeakHashMapWeakHashMap 日常开发中比较少见,它是基于普通的 Map 实现的,而里面 Entry 中的键在每一次的垃圾回收都会被清除掉,所以非常适合用于短暂访问、仅访问一次的元素,缓存在 WeakHashMap 中,并尽早地把它回收掉 。
当 Entry 被 GC 时,WeakHashMap 是如何感知到某个元素被回收的呢?
在 WeakHashMap 内部维护了一个引用队列 queue
private final ReferenceQueue<Object> queue = new ReferenceQueue<>;
这个 queue 里包含了所有被 GC 掉的键,当 JVM 开启 GC 后,如果回收掉WeakHashMap 中的 key,会将 key 放入 queue 中,在 expungeStaleEntr
ies 中遍历 queue,把 queue 中的所有 key 拿出来,并在 WeakHashMap
删除掉,以达到同步 。
private void expungeStaleEntries {for (Object x; (x = queue.poll) != ; ) {synchronized (queue) {// 去 WeakHashMap 中删除该键值对}}}
再者,需要注意 WeakHashMap 底层存储的元素的数据结构是数组 + 链表,没有红黑树哦,可以换一个角度想,如果还有红黑树,那干脆直接继承 HashMap,
然后再扩展就完事了嘛,然而它并没有这样做:
public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {}
所以,WeakHashMap 的数据结构图我也为你准备好啦 。文章插图
图中被虚线标识的元素将会在下一次访问 WeakHashMap 时被删除掉,WeakHashMap 内部会做好一系列的调整工作,所以记住队列的作用就是标志那些已经被 GC 回收掉的元素 。
关于 WeakHashMap 需要注意两点:
- 它的键是一种弱键,放入 WeakHashMap 时,随时会被回收掉,所以不能确保某次访问元素一定存在
- 它依赖普通的 Map 进行实现,是一个非线程安全的集合
- WeakHashMap 通常作为缓存使用,适合存储那些只需访问一次、或只需保存短暂时间的键值对
HashtableHashtable 底层的存储结构是数组 + 链表,而它是一个线程安全的集合,但是因为这个线程安全,它就被淘汰掉了 。
下面是 Hashtable 存储元素时的数据结构图,它只会存在数组+链表,当链表过长时,查询的效率过低,而且会长时间锁住 Hashtable 。
文章插图
这幅图是否有点眼熟哈哈哈哈,本质上就是 WeakHashMap 的底层存储结构了 。你千万别问为什么 WeakHashMap 不继承 Hashtable 哦,Hashtable 的性能在并发环境下非常差,在非并发环境下可以用 HashMap 更优 。HashTable 本质上是 HashMap 的前辈,它被淘汰的原因也主要因为两个字:性能
推荐阅读
- 已有两种太空探测器飞出我们的太阳系 飞往太阳系外的探测器
- 生科医学|全国疫情形势呈逐渐企稳态势!上海两区首日达到社会面清零目标
- 两只耳朵配不一样的助听器,助听器需要两个耳朵都配吗??
- 前端开发和后端开发的区别?这两者哪个更累?
- 如何将两个pdf合并?合并pdf的快捷方法分享
- 验孕纸两条杠是怎么回事呢
- 喝白酒时,讲究这4个“最佳”,健康饮酒醉得慢,让你多喝二两半
- 减腰两边的赘肉怎么做?
- 水陆两栖动物名字大全 水陆两栖的动物是什么动物
- 花钱学Python?不存在的!一份大纲两个网站外加搜索,足矣