HashSet 源码分析

HashSet 源码分析

1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读起来没有 IDE 方便,所以在 github 上提供JDK1.8 的源码、详细的注释及测试用例。欢迎大家 star、fork ! 2. 由于个人水平有限,对源码的分析理解可能存在偏差或不透彻的地方还请大家在评论区指出,谢谢!

1. 基本结构

1. 继承

这个类简直适合 HashMap 如出一辙,他们继承的类都极其相似。继承的是 AbstractSet

2. 实现

实现了 Set 接口,之后还有两个普遍的接口 Cloneable, java.io.Serializable 。

3. 主要字段

   这个字段非常的少,只有一个 HashMap 和一个常量。估计你已经猜到这个容器的底层是采用HashMap 实现的了,但是具体又是怎么实现的呢?    我们都知道,set 集合 是不允许有重复元素的,那么他怎么让他没有重复元素呢,答案就是把元素存放在 HashMap 的键中,因为 HashMap 的键是用来唯一区别两个 Node 节点是否相同的,而 value 就存放那个常量。

private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

4. 主要方法

  1. ctor-5
  2. add
  3. remove
  4. read/writeObject

2.主要方法分析

1. 构造方法

   这里提供了五个构造方法,其实有一个构造方法是比较特殊的,他在方法里面 new 了一个 LinkedHashMap ,也就是底层的数据结构是双链表。你可能会注意到上面我们声明的是一个 HashMap 的引用,new 的 LinkedHashMap 不会有问题吗?别忘了 后者继承了前者,并在他的基础上添加了一个双向指针。其他的四个方法其实都没什么好说的,全是调用了 HashMap 的构造,然后默认大小还是 16.

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);
}
// 包内可用! 底层采用 LinkedHashMap
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

2. add

   就是由于上面也提到了底层采用的 HashMap 结构,所以 add 就调用了 put 方法,然后看返回的值是不是 null 从而判断是否是重复元素。

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

3. remove

   remove 和上面的add 一样的操作。

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

4. read/writeObject

   和其他的容器一样重写了序列化反序列化的操作。

5.其他方法

   其他方法都是直接调用了 HashMap 的方法,所以比较简单。总共代码才三百多行,只要我们注意他的底层实现是 HashMap 就够了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云霄雨霁

字符串查找----R向单词查找树

13100
来自专栏Java进阶之路

java面试热点:集合框架(二)

21000
来自专栏Petrichor的专栏

leetcode: 100. Same Tree

11610
来自专栏个人分享

LinkedHashMap的实现原理(复习)

   LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不...

13240
来自专栏xingoo, 一个梦想做发明家的程序员

Java程序员的日常 —— 《编程思想》持有对象

集合框架可以说是Java里面必备的知识点了,日常的使用中也会遇到各种情况需要使用到集合。下面就简单介绍下各种集合的使用场景: ? List List可以看...

22480
来自专栏java一日一条

Java程序员们最常犯的10个错误

Arrays.asList()会返回一个ArrayList对象,ArrayList类是Arrays的一个私有静态类,而不是java.util.ArrayList...

6810
来自专栏java一日一条

Java 集合框架 HashSet 和 HashMap 源码剖析

之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说HashSet里面有一个Hash...

9120
来自专栏用户画像

HashSet和HashMap的区别 && HashTable和HashMap的区别

2.Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。

10230
来自专栏Java帮帮-微信公众号-技术文章全总结

【Java提高十六】集合List接口详解

在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在...

26230
来自专栏java一日一条

Java程序员们最常犯的10个错误

Arrays.asList()会返回一个ArrayList对象,ArrayList类是Arrays的一个私有静态类,而不是java.util.ArrayList...

7220

扫码关注云+社区

领取腾讯云代金券