在上一篇博客,咱们介绍了 Map 集合的一种典型实现 HashMap ,在 JDK1.8 中,HashMap 是由 数组+链表+红黑树构成,相对于早期版本的 JDK HashMap 实现,新增了红黑树做为底层数据结构,在数据量较大且哈希碰撞较多时,可以极大的增长检索的效率。了解 HashMap 的具体实现后,咱们再来介绍由 HashMap 做为底层数据结构实现的一种数据结构——HashSet。(若是不了解 HashMap 的实现原理,建议先看看 HashMap,否则直接看 HashSet 是很难看懂的)。java
HashSet 是一个由 HashMap 实现的集合。元素无序且不能重复。c#
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
和前面介绍的大多数集合同样,HashSet 也实现了 Cloneable 接口和 Serializable 接口,分别用来支持克隆以及支持序列化。还实现了 Set 接口,该接口定义了 Set 集合类型的一套规范。数组
//HashSet集合中的内容是经过 HashMap 数据结构来存储的 private transient HashMap<E,Object> map; //向HashSet中添加数据,数据在上面的 map 结构是做为 key 存在的,而value统一都是 PRESENT private static final Object PRESENT = new Object();
第一个定义一个 HashMap,做为实现 HashSet 的数据结构;第二个 PRESENT 对象,由于前面讲过 HashMap 是做为键值对 key-value 进行存储的,而 HashSet 不是键值对,那么选择 HashMap 做为实现,其原理就是存储在 HashSet 中的数据 做为 Map 的 key,而 Map 的value 统一为 PRESENT(下面介绍具体实现时会了解)。微信
①、无参构造数据结构
public HashSet() { map = new HashMap<>(); }
直接 new 一个 HashMap 对象出来,采用无参的 HashMap 构造函数,具备默认初始容量(16)和加载因子(0.75)。函数
②、指定初始容量spa
public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); }
③、指定初始容量和加载因子code
public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); }
④、构造包含指定集合中的元素对象
public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }
集合容量很好理解,这里我介绍一下什么是加载因子。在 HashMap 中,可以存储元素的数量就是:总的容量*加载因子 ,新增一个元素时,若是HashMap集合中的元素大于前面公式计算的结果了,那么就必需要进行扩容操做,从时间和空间考虑,加载因子通常都选默认的0.75。blog
public boolean add(E e) { return map.put(e, PRESENT)==null; }
经过 map.put() 方法来添加元素,在上一篇博客介绍该方法时,说明了该方法若是新插入的key不存在,则返回null,若是新插入的key存在,则返回原key对应的value值(注意新插入的value会覆盖原value值)。
也就是说 HashSet 的 add(E e) 方法,会将 e 做为 key,PRESENT 做为 value 插入到 map 集合中,若是 e 不存在,则插入成功返回 true;若是存在,则返回false。
public boolean remove(Object o) { return map.remove(o)==PRESENT; }
调用 HashMap 的remove(Object o) 方法,该方法会首先查找 map 集合中是否存在 o ,若是存在则删除,并返回该值,若是不存在则返回 null。
也就是说 HashSet 的 remove(Object o) 方法,删除成功返回 true,删除的元素不存在会返回 false。
public boolean contains(Object o) { return map.containsKey(o); }
调用 HashMap 的 containsKey(Object o) 方法,找到了返回 true,找不到返回 false。
HashSet<Integer> set = new HashSet<>(); set.add(1); set.add(2); //加强for循环 for(Integer i : set){ System.out.println(i); } //普通for循环 Iterator<Integer> iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); }
本系列教程持续更新,能够微信搜索「 IT可乐 」第一时间阅读。回复《电子书》有我为你们特别筛选的书籍资料