首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入源码探讨HashSet

深入源码探讨HashSet

作者头像
田维常
发布2020-03-25 10:35:44
3670
发布2020-03-25 10:35:44
举报

我们在工作中时常会用到HashSet,面试也有时候容易被问到,下面咱们就来聊聊HashSet

使用案例
public class Test {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("Java");
        hashSet.add("R");
        hashSet.add("C");
        hashSet.add("C#");
        hashSet.add("C#");
        hashSet.add("Java");
        hashSet.add(null);
        System.out.println("hashSet的长度:" + hashSet.size());
        //第一种遍历方式
        System.out.println("第一种方式遍历");
        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
            System.out.print(" ");
        }
        System.out.println("");
        System.out.println("第二种方式遍历");
        for (String string : hashSet) {
            System.out.print(string);
            System.out.print(" ");
        }
    }
}

输出

hashSet的长度:5
第一种方式遍历
C# null Java R C
第二种方式遍历
C# null Java R C

从上面的例子可以得知几个结果:

1,不能放入重复的。

2,不是按照放入的顺序存放的。

3,null也可以存放。

关键源码

HashSet的类图

我们来看看HashSet到底是怎么玩的

JDK1.2开始有的HashSet,实现了解耦Set,CloneableSerializable

  1. Set是个接口,定义了很多方法。
  2. Cloneable可以对象克隆。
  3. Serializable可以序列化与反序列。
  4. 继承了抽象类AbstractSet

AbstractSet也是Set接口的实现类,主要有以下几个方法:

AbstractSet实现了三个方法equalshashCoderemoveAll。然后所有继承AbstractSet的子类都不用自己去实现此三个方法。

Set定义了如下方法:

HashSet中关键的变量和方法:

//定义了一个HashMap类型的变量
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
//与备份Map中的对象关联的虚拟值
private static final Object PRESENT = new Object();
public HashSet() {
    map = new HashMap<>();
}
//设置HashSet的容量其实就是设置HashMap的容量
public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}
//求HashSet的大小就是求HashMap
public int size() {
   return map.size();
}
//往HashSet存放数据其实就是往HashMap存放数据
//数据作为key,然后value就是固定Object对象PRESENT
public boolean add(E e) {
   return map.put(e, PRESENT)==null;
}
public Iterator<E> iterator() {
   return map.keySet().iterator();
}
public int size() {
   return map.size();
}
....
//序列化与反序列化
private void writeObject(java.io.ObjectOutputStream s){
    //...
}
private void readObject(java.io.ObjectInputStream s){
    //...
}

可以看出,HashSet的操作都是基于HashMap的操作。

总结

HashSet的所有操作都是基于HashMap进行操作,用存放进HashSet的数据作为HashMap的key在使用一个固定Object对象作为HashMap的value。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用案例
  • 关键源码
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档