Collection容器家族(HashSet源码详解)
一、在Collection集合体系中的位置及概述
HashSet继承自AbstractSet抽象类,实现了Cloneable、Serializable接口,显示的实现了Set接口。至于为什么显示的实现Set接口,我前面的文章讲过。
HashSet而言,它是基于HashMap实现的,本质上讲HashSet底层实现是HashMap的封装类对象,HashSet的所有操作都是基于HashMap实现。使用HashMap来保存所有元素,因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,HashSet源码非常简单。
HashSet类,线程不安全,允许null键;
HashSet中的使用HashMap的方法,如果想要学习HashMap,请参见我的另一篇博客。
二、成员变量
// HashMap用于存储操作,HashSet底层封装类对象
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
// 与支持Map中的Object关联的虚拟值
private static final Object PRESENT = new Object();
仅有两个成员变量,map为HashSet底层的封装类对象,PRESENT为map中所有键值对的值。HashSet使用封装类对象HashMap的键存储元素,而其所有的值都使用PRESENT。
三、构造方法
// 无参构造
// 创建封装的HashMap
public HashSet() {
map = new HashMap<>();
}
// 使用集合作为参数构造本集合
public HashSet(Collection<? extends E> c) {
// 创建封装对象HashMap, 参数为c的大小和16中最大的值
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
// 使用AbstractCollection的addAll方法,它是循环遍历调用add方法实现添加元素
addAll(c);
}
// 带参构造
// 指定初始容量和加载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
// 带参构造
// 指定处事容量
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
// 带参构造
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
四、常用API
1.添加元素
public boolean add(E e) {
// 调用HashMap的put方法添加元素
return map.put(e, PRESENT)==null;
}
2.删除元素
// 删除所有元素
public void clear() {
// 调用的HashMap的clear方法
map.clear();
}
// 移除指定的元素o
public boolean remove(Object o) {
// 调用HashMap的remove方法
return map.remove(o)==PRESENT;
}
3.遍历
*/
// 获取迭代器
public Iterator<E> iterator() {
// 获取HashMap的键的Set集合的迭代器
return map.keySet().iterator();
}
4.获取元素个数
public int size() {
// 调用HashMap的size方法获取
return map.size();
}
5.判断是否包含指定键
public boolean contains(Object o) {
// 调用HashMap的containsKey获取
return map.containsKey(o);
}
6.判断是否为空
public boolean isEmpty() {
// 调用HashMap的isEmpty
return map.isEmpty();
}
五、总结
到这里HashSet就结束了,它的所有方法都是基于HashMap。