HashSet/LinkedHashSet/TreeSet
Collection 系列文章的总目录:
- Collection 体系的三个核心约定
- Sorted & Navigable
- Iterator & Iterable
- Java 中的数组
- ArrayList
- LinkedList
- HashMap
- LinkedHashMap
- TreeMap
- HashSet/LinkedHashSet/TreeSet
HashSet
HashSet
内部是直接使用HashMap
来实现的是一种变体的
装饰器模式
实现原理:
添加元素:
add() :
- 把
元素
放到 HashMap 的key
,value
放入一个常量PRESENT
删除元素:
remove():
- 从 HashMap 中 remove,并判断
value
是否等于PRESENT
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
问题:
Q:突然发现,很多集合的方法,入参都是使用 Object,而不是泛型,这是为什么?
- 集合内部依赖 Object.equals() 方法,而 Object.equals() 方法接收的参数类型是 Object 类型。Object子类如果重写了equals()方法的话,并没有要求参数类型和当前类类型一定要相同才返回true。
- 使用类似 Set<? extends Foo> set 这样的变量,除非传 null,否则编译器都会报错。因为 ? extends Foo 不是一个确定的类型,任何确定的类型,即使是Foo的子类,该方法都不能接收,因为编译期不能确定这个Foo的子类就一定是创建set时指定的那个类型。
Q:那为什么 add() 的时候需要使用泛型?
- 要保证集合内保存的元素类型
- 那些使用 Object 类型的方法,都是使用外部传入的对象去和集合内的元素做比较,而这并不强制要求传入的对象类型要求一样,只需要能和集合中的元素进行比较即可。
参考:为什么Map.containsKey()方法的参数类型是Object?
LinkedHashSet
LinkedHashSet 直接继承 HashSet
实现原理:
- HashSet提供了一个构造,可以指定使用LinkedHashMap 作为实现
- 所以 LinkedHashSet 只需要调用这个构造即可
// dummy只是用来区别不同的构造,本身并没用
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
TreeSet:
TreeSet 也是直接使用 TreeMap
实现原理:
- 和 HashSet 类似,就不再赘述了
- 内部持有的是 NavigableMap 类型,就不是 TreeMap 类型
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
public TreeSet() {
this(new TreeMap<E,Object>());
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通