-HashSet介绍
上一篇文章我们介绍了HashMap的特性,如果你了解了HashMap的源码,就会觉得HashSet真没有什么可以看得,因为它的底层全是用HashMap实现的。我们按照惯例,依旧先看官方的解释:
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
官方的解释很清楚,HashSet是由HashMap实例支持的,我们直接来看代码。
-HashSet定义
public class HashSet<E>
//很多方法在AbstractSet<E>已经实现了,例如addAll方法
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
-成员变量
//这个就是HashSet核心的底层的HashMap
private transient HashMap<E,Object> map;
//由于HashSet的元素都是作为Map的key来存储,所以这个变量其实是一个虚拟的value,每一个HashSet的值对应的value都是它,我们会在add方法中看的更清晰。
private static final Object PRESENT = new Object();
-构造函数
构造函数就更没有新意了,全是对应new一个HashMap
public HashSet() {
map = new 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);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
我对HashMap的解析的文章会在本文后面放一个链接,感兴趣的朋友可以对照这HashMap来看。
-成员函数
//从add方法可以看出,向HashSet添加一个元素实际上是向HashMap中添加一个键值对,key就是要添加的元素,value是一个固定值,这也解释了HashSet中为什么不能放重复的元素,因为HashMap的key不会重复
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
//从以下函数可以看出,有关于对HashSet的操作,实际上都被适配为对HashMap的操作,包括hash的方法,桶的结构,扩容的机制都是跟HashMap一样,因为在我的理解,HashSet就大概等于是HashMap的适配类。
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
public void clear() {
map.clear();
}
总结:由以上分析我们可以看出,HashSet的底层完全是由HashMap来支持的,HashSet把要添加的元素作为HashMap的key,存入键值对中(value是一个固定值PRESENT ),这也是HashSet为什么没有重复值的原因,因为HashMap的key不能重复,在我的理解,HashSet就大概等于是HashMap的适配类。
这里是我有关于HashMap的文章,有想理解HashMap底层实现的朋友可以看一看