前言
jdk 版本 jdk1.8.0_161
UML结构图
说明:结构 和 前面的 ArrayList 以及 LinkedList 很类似。
Set:不包含重复元素的 集合 ,从 它的名字可以看出,该接口的模型是 数学上的 Set (集合)抽象。数学上的集合 的特性是 无序性,确定性,互异性。
AbstractSet:Set 接口的骨架实现;
HashSet:实现了 Set 接口,由 哈希表( hash table ) 支持(内部数据结构实际上是一个 HashMap 实例,值保存在HashMap实例的 key 中)。不能保证集合的迭代顺序,支持 null 值,不包含重复的元素。
假设 哈希函数将 元素 正确地分散在 桶(buckets)中, 那么该类的 add , remove , contains, size 方法 均为 常量时间。在这个集合上迭代的时间 和 HashSet 实例的 size(即元素数量) 加上 支持 HashMap 实例 容量 (桶的数量)的总和 是成比例的。因此,如果对迭代要求比较高的,不要设置太大的初始化容量,也不要设置太低的 加载因子。
源码分析
构造函数:
private transient HashMap<E,Object> map;
/**
* 构造一个新的,空的集合
* HashMap 实例有默认的初始化容量16 以及 默认的加载因子 0.75
*/
public HashSet() {
map = new HashMap<>();
}
/**
*构造一个包含指定集合元素的集合
* HashMap 使用默认的加载因子
* 以及足以容纳元素的初始容量的初始化容量初始化
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); //计算最小容量
addAll(c);
}
/**
* 制定初始化容量 和 加载因子
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
/**
* 指定初始化容量,使用默认的加载因子 0.75
*/
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
/**
* 构造一个新的, 空的 LinkedHashSet
* 作用域为 默认的,即包内可见
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
内部数据结构
HashMap 实例:相关方法 均来自于 HashMap 类中的 实现方法
private transient HashMap<E,Object> map;
增删源码
源码分析参看 集合学习——Map 之 HashMap
增加一个元素:
/**
* 如果指定元素不存在的话,将元素添加到 Set 集合中.
* 如果 集合中已经存在该元素,集合保持不变,并且返回 false
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
private transient HashMap<E,Object> map;
// map 中 键 的对应值 均为 该对象
private static final Object PRESENT = new Object();
删除元素:
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}