在绍了 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. C#短链接生成方法

    public class Program { static void Main() { Random rd = new Random(); for (int i = 0; i < 10; i++ ...

  2. osharp多租户方案

    osharp多租户方案 租户信息 using System; using System.Collections.Generic; using System.Linq; using System.Tex ...

  3. iterm2配置ssh自动登录

    iterm2 ssh 演示 cmd + o 打开服务器列表,方向键选择要登录的机器,回车,提示输入密码: option + cmd + f 打开密码管理器,方向键选择密码,回车,即可登录:(这一步通过 ...

  4. [SDR] GNU Radio 系列教程 —— GNU Radio RX PDU (接收据包操作)的基础知识(超全)

    目录 1 接收概述 2 相关块介绍 2.1 相关性估计器(Correlation Estimator) 2.2 多相时钟同步(Polyphase Clock Sync) 2.3 线性均衡器(Linea ...

  5. [WPF]XAML中使用IMultiValueConverter实现Command的多参数传参

    问题 如何对ICommand传入多个参数? 背景 最近在做一个WPF的开发,有多个相近的功能写了不同的Command,因为要对应不同的对象.因为是CtrlCV,显得代码有点冗赘不够优雅,但是IComm ...

  6. MySQL-InnoDB行锁

    InnoDB的锁类型 InnoDB存储引擎支持行锁,锁类型有两种: 共享锁(S锁) 排他锁(X锁) S和S不互斥,其他均互斥. 除了这两种锁以外,innodb还支持一种锁,叫做意向锁. 那么什么是意向 ...

  7. SQLServer中事务处理

    --将当前库存记录insert医废转移单中 --declare @Warehouse nvarchar(100); declare @Warehouse_JJRID nvarchar(100); de ...

  8. FastAPI中的依赖注入与数据库事务管理

    title: FastAPI中的依赖注入与数据库事务管理 date: 2025/04/09 00:10:29 updated: 2025/04/09 00:10:29 author: cmdragon ...

  9. sql查询语句典例整理

    简单查询: 1.SELECT * FROM 表名称 WHERE 字段名 LIKE '查询内容' 1). SELECT * FROM member WHERE NickName LIKE '贝克汉姆': ...

  10. jmeter使用json断言校验返回结果

    jmeter断言有好几种方式,本案讲json断言 http请求返回数据的格式有json格式,如下图,比如需要验证"ShipperRealName"参数的值 步骤如下: 第一步,选中 ...