HashSet 本身并没有什么特别的东西,它提供的所有集合核心功能,都是基于HashMap来实现的。如果了解HashMap源码的实现,HashSet 源码看起来跟玩一样。我的博客中有专门分析HashMap源码的文章,不熟悉的请自行翻阅。 HashSet 的特点如下: - 内部使用HashMap的key存储元素,以此来保证**元素不重复**; - HashSet是无序的,因为HashMap的key是**无序**的; - HashSet中允许有一个null元素,因为HashMap允许key为null; - HashSet是**非线程安全**的。 ```java public class HashSet extends AbstractSet implements Set, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; // 基于HashMap实现 private transient HashMap map; // 只需要用到HashMap中key唯一的特性,所以value全部使用同一个 Object实例填充,节省内存空间 private static final Object PRESENT = new Object(); /** * 实例化 HashSet 的时候,初始化内部的 HashMap */ public HashSet() { map = new HashMap<>(); } /** * 根据一个集合实例,实例化 HashSet */ public HashSet(Collection c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } /** * 根据初始容量和扩容因子实例化 HashSet,减少rehash频率,提升性能,原理与HashMap相同 */ 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 来实现的 */ public Iterator iterator() { return map.keySet().iterator(); } /** * 元素个数 */ public int size() { return map.size(); } /** * 是否为空 */ public boolean isEmpty() { return map.isEmpty(); } /** * 是否包含给定元素 */ public boolean contains(Object o) { return map.containsKey(o); } /** * 添加元素,如果 Set集合中未包含该元素,返回true */ public boolean add(E e) { return map.put(e, PRESENT)==null; } /** * 删除元素,如果Set集合包含该元素,返回true */ public boolean remove(Object o) { return map.remove(o)==PRESENT; } /** * 清除元素 */ public void clear() { map.clear(); } /** * 浅克隆 */ @SuppressWarnings("unchecked") public Object clone() { try { HashSet newSet = (HashSet) super.clone(); newSet.map = (HashMap) map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(e); } } } ```