源码解读--HashSet

21 篇文章 0 订阅
13 篇文章 0 订阅

一.序言

 先说一下HashSet的特性:添加的是对象;值不会重复;内部实现用的是HashMapjava源码系列

老套路,看看图谱,看它是何方神圣。


简单的来说,好像没发现什么,就是Set集合而已。

二.源码

精简一点,和之前一样,只讲解一两个增删查的方法,更深的需要同学们去发掘。

1初始化

它有五个初始化方法HashSet(),HashSet(Collection),HashSet(int),HashSet(int ,float),HashSet(int ,float,boolean)

1.1 HashSet()方法

public HashSet() {  //直接就建了一个HashMap对象,我们都知道Map是K-v接口,按道理有两个呀,HashSet但是只存一个值,什么情况?不急,我们往下看。
    map = new HashMap<>();
}

1.2 HashSet(Collection) 方法

public HashSet(Collection<? extends E> c) {  //初始化的时候添加的是一个集合,这个HashMap的初始容量设置为,(集合个数*1.25 +1)和16取最大值 
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);  //把这个集合加到这个map中
}
public boolean addAll(Collection<? extends E> c) {  //具体添加方法
    boolean modified = false;
    for (E e : c)
        if (add(e))  //这里有意思了,看下面贴出来的方法
            modified = true;
    return modified;
}
public boolean add(E e) {  //哈哈 ,被我抓住了,原来key是我们的添加的值,V 是一个对象
    return map.put(e, PRESENT)==null;  //PERSENT定义为 private static final Object PRESENT = new Object() 没看错, 就是一个对象
}

1.3HashSet(int)  方法

public HashSet(int initialCapacity) {  //初始HashMap的容量
    map = new HashMap<>(initialCapacity); 
}

1.4 HashSet(int ,float)  第一个参数是容量,第二个参数我猜猜看,应该是负载因子吧,不信看源码

public HashSet(int initialCapacity, float loadFactor) {  //看,没骗你吧
    map = new HashMap<>(initialCapacity, loadFactor); 
}

1.5HashSet(int ,float,boolean)  那第三个参数是什么呢?

HashSet(int initialCapacity, float loadFactor, boolean dummy) {  逗我玩呢? dummy 这个参数根本就没有用
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

2.添加 (重点)

public boolean add(E e) {  //纳尼,这就完了,不是说key相同的会覆盖吗?怎么体现的?
    return map.put(e, PRESENT)==null;  //这里面用的是HashMap,简单教大家一个记忆方法,HashMap的key是不是唯一的?对的,你们一般都是这样回答的,那这里HashSet里面的值也是唯一的,我记得HashMap可是支持Null作为key,也就是HashSet可以存放null。HashMap里面的东西这里就不累述了。
}
3.删除
public boolean remove(Object o) {  //这里调用的是HashMap里面的remove方法,
    return map.remove(o)==PRESENT;  //判断移除的对象是对象,因为HashSet存的时候对应hashMap的V也是对象
}

4 查找

public boolean contains(Object o) {  //我去,又是map的方法,
    return map.containsKey(o);
}
说实话,今天我也是第一次看HashSet源码,没想到里面的实现竟然是HashMap,那这么说HashMap的问题,它都有咯

1.顺序不固定,我们知道HashMap会扩容,之后顺序高低位不一样(jdk8是这样,jdk是再hash,hash的自然是新数组的长度哈),

2.不是线程安全的。

三.使用

public void HashSetTest() {
    Set<String> strings = new HashSet<String>();
    strings.add("a");
    strings.add("b");
    strings.add("c");
    strings.add("a");
    for (String s : strings) {
        System.out.println(s);
    }
}

输出:

a

b

c

探究:到底这个输出的a是代码中第一个存入的a,还是第四个存入的a?

看过源码就知道,HashMap在添加值的执行,先找map里面有没有key相同的,如果找到了,这个key是不动的,只是把值(V)覆盖了,HashMap找到key跟新值(v)源码如下:

if (e != null) { // 找到我们的key相同的,key没有动,到时值被赋了新值
    V oldValue = e.value;
    if (!onlyIfAbsent || oldValue == null)
        e.value = value;
    afterNodeAccess(e);
    return oldValue;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值