在绍了 Map 集合的一种典型实现 HashMap之后 ,我们知道,自Java 8起HashMap 是由数组+但链表+红黑树构成,相对于早期版本的 HashMap 实现,新增了红黑树作为底层数据结构,在数据量较大且哈希碰撞较多时,能够极大的增加检索的效率。我们今天在此基础之上,再来介绍由 HashMap 作为底层数据结构实现的一种数据结构——HashSet。

HashSet 定义

HashSet 是一个由 HashMap 实现的集合。元素无序且不能重复。

1 public class HashSet

2 extends AbstractSet

3 implements Set, Cloneable, java.io.Serializable

HashSet

  和前面介绍的大多数集合一样,HashSet 也实现了 Cloneable 接口和 Serializable 接口,分别用来支持克隆以及支持序列化。还实现了 Set 接口,该接口定义了 Set 集合类型的一套规范。

字段属性

//HashSet集合中的内容是通过 HashMap 数据结构来存储的
private transient HashMap<E,Object> map; //向HashSet中添加数据,数据在上面的 map 结构是作为 key 存在的,而value统一都是 PRESENT
private static final Object PRESENT = new Object();

  第一个定义一个 HashMap,作为实现 HashSet 的数据结构;第二个 PRESENT 对象,因为前面讲过 HashMap 是作为键值对 key-value 进行存储的,而 HashSet 不是键值对,那么选择 HashMap 作为实现,其原理就是存储在 HashSet 中的数据 作为 Map 的 key,而 Map 的value 统一为 PRESENT(下面介绍具体实现时会了解)。

常用构造函数

无参构造

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

直接 new 一个 HashMap 对象出来,采用无参的 HashMap 构造函数,使用默认初始容量(16)和加载因子(0.75)。

指定初始容量

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

指定初始容量和加载因子

public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}

构造包含指定集合中的元素

public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}

  集合容量很好理解,这里我介绍一下什么是加载因子。在 HashMap 中,能够存储元素的数量就是:总的容量*加载因子 ,新增一个元素时,如果HashMap集合中的元素大于前面公式计算的结果了,那么就必须要进行扩容操作,从时间和空间考虑,加载因子一般都选默认的0.75。

常用方法

本节介绍HashSet中的常用方法。

添加元素

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

  通过 map.put() 方法来添加元素,在上一篇博客介绍该方法时,说明了该方法如果新插入的key不存在,则返回null,如果新插入的key存在,则返回原key对应的value值(注意新插入的value会覆盖原value值)。

  也就是说 HashSet 的 add(E e) 方法,会将 e 作为 key,PRESENT 作为 value 插入到 map 集合中,如果 e 不存在,则插入成功返回 true;如果存在,则返回false。

删除元素

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

  调用 HashMap 的remove(Object o) 方法,该方法会首先查找 map 集合中是否存在 o ,如果存在则删除,并返回该值,如果不存在则返回 null。

  也就是说 HashSet 的 remove(Object o) 方法,删除成功返回 true,删除的元素不存在会返回 false。

查找元素

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

调用 HashMap 的 containsKey(Object o) 方法,找到了返回 true,找不到返回 false。

遍历元素

HashSet<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
//增强for循环 5 for(Integer i : set){
System.out.println(i);
}

Java 17 java.util.HashSet 类源码分析的更多相关文章

  1. Java集合:HashSet的源码分析

    Java集合---HashSet的源码分析   一.  HashSet概述: HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特别是它不保证该 ...

  2. java-通过 HashMap、HashSet 的源码分析其 Hash 存储机制

    通过 HashMap.HashSet 的源码分析其 Hash 存储机制 集合和引用 就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并非真正的把 Java 对象放入数组中.仅仅是把对象的 ...

  3. List 接口以及实现类和相关类源码分析

    List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...

  4. Java Properties类源码分析

    一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...

  5. java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析

    java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...

  6. Java并发编程笔记之Unsafe类和LockSupport类源码分析

    一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...

  7. lesson2:java阻塞队列的demo及源码分析

    本文向大家展示了java阻塞队列的使用场景.源码分析及特定场景下的使用方式.java的阻塞队列是jdk1.5之后在并发包中提供的一组队列,主要的使用场景是在需要使用生产者消费者模式时,用户不必再通过多 ...

  8. Java ThreadPoolExecutor线程池原理及源码分析

    一.源码分析(基于JDK1.6) ThreadExecutorPool是使用最多的线程池组件,了解它的原始资料最好是从从设计者(Doug Lea)的口中知道它的来龙去脉.在Jdk1.6中,Thread ...

  9. Java入门系列之集合LinkedList源码分析(九)

    前言 上一节我们手写实现了单链表和双链表,本节我们来看看源码是如何实现的并且对比手动实现有哪些可优化的地方. LinkedList源码分析 通过上一节我们对双链表原理的讲解,同时我们对照如下图也可知道 ...

  10. Java入门系列之集合ArrayList源码分析(七)

    前言 上一节我们通过排队类实现了类似ArrayList基本功能,当然还有很多欠缺考虑,只是为了我们学习集合而准备来着,本节我们来看看ArrayList源码中对于常用操作方法是如何进行的,请往下看. A ...

随机推荐

  1. Elasticsearch搜索引擎学习笔记(四)

    分词器 内置分词器 standard:默认分词,单词会被拆分,大小会转换为小写. simple:按照非字母分词.大写转为小写. whitespace:按照空格分词.忽略大小写. stop:去除无意义单 ...

  2. vue3用vite新建项目

    1. npm init vue@latest vue3-project 调用create-app创建, 指定了目录是vue3-projece,但是,紧接着有一堆配置要询问. 2. npm create ...

  3. 08_使用python 内置 json 实现数据本地持久化

    使用python 内置 json 实现数据本地持久化 四个json函数 函数 json.load() 将本地json数据文件读取出来,并以列表形式返回从文件对象中读取 JSON 格式的字符串,并将其反 ...

  4. Supac 如何修改地址界限高层点

    编辑->图层->运算 2.选择z ->填写高度 如-180阶段 3.保存

  5. hexo 本地启动项目 hexo-browsersync 不工作原因总结

    问题 1 : hexo-server 开启 compress 压缩后 hexo-browsersync 插件热更新完全无效,没办法自动刷新 此问题表现在 hexo 任何版本 问题原因: hexo-se ...

  6. 【BUG】axios 长数字精度丢失问题

    问题原因 出现改问题是于javascript 整数范围问题 java 中 Long 类型 -2的63次方 - 2的63次方减去1 但是javascript整数范围确没有那么大,导致Long数字过大前端 ...

  7. k8s v1.16.3,Unable to connect to the server: x509: certificate has expired or is not yet valid

    前言 kubernetes 版本为 v1.16.3 使用 kubelet get node 后报错: x509: certificate has expired or is not yet valid ...

  8. mac ssh 密钥登陆远程服务器

    第一步 创建ssh文件目录 打开终端 执行: mkdir ~/.ssh 第二步 将密钥对移到ssh目录下 mv ~/Downloads/MyKeyPair.pem ~/.ssh/MyKeyPair.p ...

  9. mongodb删除某个字段

    如下 db.yourcollection.update({ "需要删除的字段": { "$exists": true } }, { "$unset&q ...

  10. Solana编译失败探讨(OpenEuler RISC-V版)

      Solana 是 2017 年由 Anatoly Yakovenko 创立的开源项目,旨在打造高性能.去中心化且低成本的区块链平台2.它采用独特的 Proof of History(PoH)共识机 ...