一、HashSet解读
在讲HashSet底层数据结构之间我们不妨先来浏览下HashSet的源码,因为它很懒,为什么说它懒,是因为它底层是用的HashMap,没有自己的实现,甚至一些常量都是直接用的HashMap中的,数组初始化容量、装载因子等。
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
读完上述HashSet构造方法,可以看到全是使用HashMap的构造方法实现,在上篇HashMap源码博客中提到,HashMap构造方法只是做一些常量设定,并没有创建任何对象。
1、HashSet添加元素
与HashMap添加元素方法不同,HashSet添加元素方式时add(),且只有唯一的一个add()方法boolean add(E e),参数为要添加的数据。
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
HashSet的add()方法中调用了HashMap的put(k,v)方法,key值是传入的数据,value为PRESENT,为一个空对象。
HashSet的本质是一个"没有重复元素"的集合,它是通过HashMap实现的。HashSet中含有一个"HashMap类型的成员变量"map,HashSet的操作函数,实际上都是通过map实现的。HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个空对象。
2、HashSet移除元素
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
HashSet移除元素直接调用HashMap的remove()方法,原理自然一致。
二、HashSet数据结构
由于底层使用的是HashMap实现,数据结构和HashMap类似,都是数组+链表+红黑树,最大的区别是HashSet没有value值,把存储的数据直接放在HashMap的key上,所有HashSet具有与HashMap相似的优势,检索数据相当快,boolean contains(Object o)方法效率高,添加元素add()方法相对其他类型集合来说有较大优势,但是遍历全部元素效率低。
如果元素要存储到HashSet集合中,必须重写hashCode方法和equals方法。