HashSet源码解析

来源:互联网 发布:旅游大数据第一股 编辑:程序博客网 时间:2024/05/29 20:00

-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底层实现的朋友可以看一看

HashMap源码分析

原创粉丝点击