Java设计模式之适配器模式:深入JDK源码探秘Set类

在Java编程中,Set类作为一个不允许存储重复元素的集合,广泛应用于数据去重、集合运算等场景。然而,你是否曾好奇Set类是如何在底层实现元素唯一性判断的?这背后隐藏的力量正是适配器模式。

适配器模式简介

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换成客户端期望的另一个接口,从而使原本不兼容的类可以一起工作。适配器模式的核心思想是通过适配器类来转换接口,使得原本由于接口不兼容而不能一起工作的类能够协同工作。

在适配器模式中,通常包含三个角色:

  1. Target(目标接口):定义客户端所期待的接口。
  2. Adaptee(适配者):已经存在的类,需要适配的类,它提供了一些有用的方法,但接口不符合客户端的要求。
  3. Adapter(适配器):适配器类,它实现了目标接口,并将请求转发给适配者类。
Set类中的适配器模式应用

在JDK源码中,Set类的实现巧妙地运用了适配器模式。具体来说,HashSet、LinkedHashSet和TreeSet这三个主要的Set实现类,都通过适配器模式实现了各自的功能。

  1. HashSet

HashSet内部持有一个transient的HashMap实例,通过HashMap的键的唯一性来保证Set中元素的唯一性。当我们调用HashSet的add方法时,实际上是将元素作为HashMap的键,而一个固定的PRESENT对象作为值,存入了HashMap中。这样一来,通过HashMap键的唯一性,就轻松保证了Set中元素的唯一性。

复制代码

java复制代码

|---|-------------------------------------------------------|
| | private transient HashMap<E,Object> map; |
| | private static final Object PRESENT = new Object(); |
| | |
| | public boolean add(E e) { |
| | return map.put(e, PRESENT) == null; |
| | } |

获取HashSet的迭代器时,它直接返回的是HashMap的键集合的迭代器,这使得我们在遍历HashSet时,实际上是在遍历HashMap的键,从而获取到Set中的所有元素。

复制代码

java复制代码

|---|-----------------------------------|
| | public Iterator<E> iterator() { |
| | return map.keySet().iterator(); |
| | } |

  1. LinkedHashSet

LinkedHashSet在构造函数中调用了父类的构造函数,最终创建了一个LinkedHashMap。LinkedHashSet利用LinkedHashMap的有序特性,不仅实现了元素的唯一性,还能保持元素插入的顺序,为我们提供了一种有序的Set实现。

复制代码

java复制代码

|---|-----------------------------------------------------------------|
| | public LinkedHashSet(int initialCapacity, float loadFactor) { |
| | super(initialCapacity, loadFactor, true); |
| | } |

其构造函数最终会调用到类似这样的父类构造函数,创建一个LinkedHashMap实例。

复制代码

java复制代码

|---|-------------------------------------------------------------------|
| | HashSet(int initialCapacity, float loadFactor, boolean dummy) { |
| | map = new LinkedHashMap<>(initialCapacity, loadFactor); |
| | } |

  1. TreeSet

TreeSet内部持有一个transient的NavigableMap实例,通过将元素存储在NavigableMap中,并利用其排序功能,实现了对元素的有序存储和操作,为我们提供了一个有序且不重复的Set集合。

复制代码

java复制代码

|---|-------------------------------------------------------|
| | private transient NavigableMap<E,Object> m; |
| | private static final Object PRESENT = new Object(); |

适配器模式的优势

通过适配器模式,Set类实现了与不同底层数据结构(如HashMap、LinkedHashMap和TreeMap)的无缝对接,从而提供了高效且灵活的集合操作。适配器模式的优势主要体现在以下几个方面:

  1. 提高了类的复用性:通过适配器模式,我们可以将已有的类进行复用,而无需修改其结构。
  2. 提高了系统的灵活性和可扩展性:当需要引入一个新的接口时,只需增加一个新的适配器类,而无需修改原有代码。
  3. 降低了系统间的耦合度:通过适配器模式,我们可以将原本紧密耦合的两个系统解耦,从而提高系统的可维护性和稳定性。
总结

通过深入剖析JDK源码中Set类对适配器模式的应用,我们不仅揭开了Set类高效实现元素唯一性判断和操作的神秘面纱,更深刻体会到了设计模式在优化代码结构、提高代码复用性和灵活性方面的巨大威力。在日常编程中,我们应深入源码,学习大师们的设计思路和技巧,不断提升自己的编程水平,打造出更加高效、健壮、优雅的软件系统。

相关推荐
Zzz 小生32 分钟前
Github-Cursor Free VIP:解锁AI编程工具的高级功能
github·ai编程
UVM_ERROR1 小时前
硬件设计实战:解决Valid单拍采样失效问题(附非阻塞赋值与时序对齐核心要点)
驱动开发·fpga开发·github·芯片
散峰而望1 小时前
C++数组(三)(算法竞赛)
开发语言·c++·算法·github
逻辑棱镜2 小时前
Git 分支管理与提交信息规范 (v1.0)
git·github·团队开发·代码规范·敏捷流程
qinyia5 小时前
WisdomSSH解决因未使用Docker资源导致的磁盘空间不足问题
运维·服务器·人工智能·后端·docker·ssh·github
b***65326 小时前
【解决】RESP.app GUI for Redis 连接不上redis服务器
服务器·redis·github
mortimer12 小时前
破局视频翻译【最后一公里】––从语音克隆到口型对齐的完整工程思路
python·github·aigc
散峰而望15 小时前
C++数组(二)(算法竞赛)
开发语言·c++·算法·github
码农很忙20 小时前
从零开始搭建个人博客:基于Hexo + GitHub Pages的完整指南
github
徐同保20 小时前
如何使用GitKraken把git项目迁移到另一个平台,并保存所有提交记录,例如把github上的项目,迁移到gitee
git·gitee·github