Collection(3) HashSet源码解析

Collection系列

  1. HashMap --> HashMap源码解析_yolan6824的博客-CSDN博客
  2. LinkedHashMap --> LinkedHashMap源码解析_yolan6824的博客-CSDN博客
  3. HashSet --> 本篇

先导

我们知道,HashSet可以用来存储不同的元素。即使add两个相同的元素,在HashSet里面也只会保存其中的一个。所以HashSet可以用来去重。

看到这里,我们会产生一个问题:

  1. HashSet是怎么去重的?它是依据什么去重的?

实现

HashSet基本结构

看一下HashSet的基本结构:

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    public HashSet() {
        map = new HashMap<>();
    }
}

很容易可以看出,HashSet持有一个HashMap的实例。

至此可以猜测一下HashSet就是依靠的HashMap执行的去重,因为HashMap的key是唯一的。那么回忆一下,HashMap的key是如何保持唯一的?

当HashMap执行put操作的时候,会根据key的hashcode()求出它在HashMap维护的数组中的index。HashMap是依据 链表/红黑树 解决哈希冲突的,所以遍历该index对应的 链表/红黑树 即可以找到这个key。如果找到这个key,就直接替换key对应的value。否则,新建一个Node。

经历了查找,查找不到再新建的步骤,自然就可以保持HashMap中的key唯一的特性了。

所以可以大胆猜测,HashSet就是利用了HashMap中的key唯一的特性,实现了自己的数据结构。

HashSet方法实现

知道了HashSet的基本数据结构,下面考究下HashSet的一些基本方法来验证一下自己的猜想。

// HashSet.java
public boolean add(E e) {
     return map.put(e, PRESENT)==null;
}    

public boolean remove(Object o) {
     return map.remove(o)==PRESENT;
}

public boolean contains(Object o) {
     return map.containsKey(o);
}

public void clear() {
     map.clear();
}

没错,,,,HashSet的方法真的如此简洁,,,

add

add方法简单调了HashMap.put方法,key为传入的参数,即验证了上面我们的猜想,HashSet就是利用了HashMap的key实现了去重。

map.put的返回值为null,代表这个key之前存入的值为null 或 之前没有这个key。既然map对应key存入的value都是PRESENT,这就代表,HashSet.add方法返回true,代表之前HashSet中没有存有这个元素。

remove

调用HashMap.remove方法,remove()方法返回值为null,代表该key对应的value为空,或之前不存在这个key。所以HashSet.remove方法返回true,代表HashSet中之前存在过这个key。

contains

调用HashMap.containsKey。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值