Java的HashSet源码分析

CKEditor5富文本编辑器 - 视频引入、预览及自定义toolbar 文章目录定义遇到的问题视频部分引入媒体url失败原因解决方法:自定义视频provider视频预览及页面不显示视频问题解决方案:H5 \标签如何移除toolbar中的部分插件 一个小后端很少接触前端框架,只能在知识的海洋中漂泊。。。 定义 <script src="https://cdn.ckeditor.com/ckeditor5/16.0.0/classic/ckeditor.js"&gt... 阅读详情

前言

在编程的世界里,有一种神奇的工具,它小巧却强大,灵活而可靠,它就是 HashSet。然而,你是否曾经好奇过,这么强大的工具,其背后的实现原理是怎样的呢?今天,让我们一起揭开 HashSet 源码的神秘面纱,探索这个 Java 世界中的神奇数据结构。

首先,我们需要明白,HashSet 并不是一个简单的集合,它是基于哈希表实现的一种集合。哈希表是一种数据结构,通过哈希函数将元素映射到数组的一个位置,实现快速的查找。而 HashSet 则在此基础上,增加了一些额外的功能,使得它在存储和查找元素时更加高效。

在这里插入图片描述

优点

HashSet是一种非常常用的集合类型,因为它具有许多优点:

  1. 快速查找: HashSet内部是基于哈希表实现的,这意味着你可以在常数时间内(O(1))查找元素,无论集合中有多少元素。这使得HashSet非常适用于需要快速查找元素的场景,例如检查元素是否存在。
  2. 高效去重: 由于HashSet不允许重复元素,它提供了一种方便的方式来去重。无论你有多少重复的元素,最终HashSet中只会包含唯一的元素,这可以大大简化去重操作。
  3. 无序性: HashSet中的元素是无序的,它不维护元素的插入顺序或排序顺序。这在某些情况下可以带来性能上的优势,因为不需要维护元素的顺序。
  4. 线程不安全: HashSet是非线程安全的,这意味着在多线程环境中使用HashSet可能需要额外的同步措施。如果需要在多线程环境中使用,可以考虑使用Collections.synchronizedSet()方法来创建线程安全的HashSet。

HashSet的内部实现

HashSet的内部实现是基于HashMap,实际上,HashSet是通过创建一个基于HashMap的实例来实现的。HashSet使用HashMap中的键来存储集合中的元素,而值始终是一个虚拟常量(PRESENT),它在HashSet中不起实际作用。

注意事项

虽然HashSet在许多场景中非常有用,但也有一些需要注意的事项:

  1. 无序性: 如果你需要按照元素的插入顺序或特定顺序遍历集合元素,HashSet可能不适合你。在这种情况下,可以考虑使用LinkedHashSet,它是HashSet的一个变种,保留了元素的插入顺序。
  2. 哈希冲突: 在HashSet内部,不同的元素可能会产生相同的哈希码,这被称为哈希冲突。HashSet使用链表解决哈希冲突,当链表长度超过一定阈值时,链表会转换为红黑树以提高性能。
  3. 元素类型: HashSet中的元素需要正确实现hashCode()和equals()方法,以确保元素能够正确存储和查找。如果你自定义了类,并将其用作HashSet中的元素,务必重写这两个方法。

工作原理

那么,HashSet 是如何工作的呢?它的工作原理可以简化为以下几个步骤:

初始化:当我们创建一个 HashSet 对象时,它会调用构造函数,创建一个新的哈希表。

/**
 * 构造一个空的 `HashSet`,具有默认的初始容量(16)和默认的负载因子(0.75)。
 */
public HashSet() {
    map = new HashMap<>();
}

/**
 * 构造一个包含指定集合中元素的新集合。`HashMap` 使用默认的负载因子(0.75)和足够容纳指定集合中元素的初始容量。
 *
 * @param c 要放入此集合的元素的集合
 * @throws NullPointerException 如果指定的集合为null
 */
public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
}

/**
 * 构造一个新的、空的集合;底层的 `HashMap` 实例具有指定的初始容量和默认的负载因子(0.75)。
 *
 * @param      initialCapacity   哈希表的初始容量
 * @throws     IllegalArgumentException 如果初始容量小于零
 */
public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}


/**
 * 构造一个新的、空的集合;底层的 `HashMap` 实例具有指定的初始容量和指定的负载因子。
 *
 * @param      initialCapacity   哈希映射的初始容量
 * @param      loadFactor        哈希映射的负载因子
 * @throws     IllegalArgumentException 如果初始容量小于零,或者负载因子不是正数
 */
public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
}

/**
 * 构造一个新的、空的链式哈希集合。 (这是包私有构造函数,仅由LinkedHashSet使用。)底层的
 * HashMap 实例是一个具有指定初始容量和指定负载因子的LinkedHashMap。
 *
 * @param      initialCapacity   哈希映射的初始容量
 * @param      loadFactor        哈希映射的负载因子
 * @param      dummy             忽略的参数(用于区分此构造函数和其他int、float构造函数。)
 * @throws     IllegalArgumentException 如果初始容量小于零,或者负载因子不是正数
 */
public HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

  • public HashSet(): 默认构造方法创建一个具有默认初始容量(16)和默认负载因子(0.75)的 HashSet 对象。
  • HashSet(Collection<? extends E> c): 构造函数接受一个集合作为参数,将集合中的元素放入新的HashSet中。它会根据集合的大小自动计算合适的初始容量,并使用默认的负载因子0.75。
  • public HashSet(int initialCapacity): 带初始容量参数的构造方法创建一个具有指定初始容量和默认负载因子的 HashSet 对象。
  • public HashSet(int initialCapacity, float loadFactor): 带初始容量和负载因子参数的构造方法创建一个 HashSet 对象。
  • public HashSet(int initialCapacity, float loadFactor, boolean dummy): 这个构造函数是包私有的,仅供LinkedHashSet使用。它创建一个基于LinkedHashMap的HashSet,允许指定初始容量和负载因子,同时忽略了一个名为dummy的参数。

插入:当我们向HashSet中插入一个元素时,首先会使用元素的hashCode()方法计算出其在哈希表中的位置,然后检查该位置是否已经有Node对象存在。如果不存在,则创建一个新的Node对象并放入该位置;如果存在,则不执行插入操作。

/**
 * 将指定的元素添加到 `HashSet` 中。
 */
public boolean add(E e) {
    return map.put(e, PRESENT) == null;
}
  • public boolean add(E e): 此方法将指定的元素添加到 HashSet 中。它实际上是通过调用底层的 HashMap 的 put 方法来实现的。如果 put 方法返回 null,则表示元素之前不存在,插入成功。

查找:当我们需要查找一个元素是否存在于HashSet中时,同样会先计算元素的hashCode()值,然后根据该值找到数组中的一个位置。如果该位置的Node对象包含要查找的元素,返回true,否则返回false。

/**
 * 如果 `HashSet` 包含指定的元素,则返回 `true`。
 */
public boolean contains(Object o) {
    return map.containsKey(o);
}
  • public boolean contains(Object o): 此方法用于检查 HashSet 是否包含指定的元素。它实际上是通过调用底层的 HashMap 的 containsKey 方法来实现的。

删除:当我们需要从HashSet中删除一个元素时,首先计算元素的hashCode()值,然后检查该位置的Node对象是否包含要删除的元素。如果包含,则将该元素从哈希表中移除;如果不包含,则不执行删除操作。

/**
 * 如果 `HashSet` 中存在指定的元素,则将其删除。
 */
public boolean remove(Object o) {
    return map.remove(o) == PRESENT;
}
  • public boolean remove(Object o): 此方法用于从 HashSet 中删除指定的元素。它实际上是通过调用底层的 HashMap 的 remove 方法来实现的。如果 remove 方法返回 PRESENT,则表示删除成功。

使用场景

在Java中,HashSet是一个常用的数据结构,适用于多种编程场景。以下是一些常见的HashSet使用场景,每个场景都伴随着相应的Java代码示例:

1. 去重数据

import java.util.HashSet;

public class DeduplicationExample {
    public static void main(String[] args) {
        HashSet<String> uniqueNames = new HashSet<>();
        
        uniqueNames.add("Alice");
        uniqueNames.add("Bob");
        uniqueNames.add("Alice"); // 重复元素,不会被添加
        
        System.out.println(uniqueNames); // 输出: [Bob, Alice]
    }
}

2. 快速成员检查

import java.util.HashSet;

public class MemberCheckExample {
    public static void main(String[] args) {
        HashSet<Integer> numbers = new HashSet<>();
        
        numbers.add(10);
        numbers.add(20);
        
        boolean contains = numbers.contains(10); // 成员检查
        
        System.out.println("Contains 10: " + contains); // 输出: Contains 10: true
    }
}

3. 查找交集、并集和差集

import java.util.HashSet;

public class SetOperationsExample {
    public static void main(String[] args) {
        HashSet<Integer> set1 = new HashSet<>();
        HashSet<Integer> set2 = new HashSet<>();
        set1.add(1);
        set1.add(2);
        set1.add(3);

        set2.add(2);
        set2.add(3);
        set2.add(4);

        // 交集
        set1.retainAll(set2);
        System.out.println("Intersection: " + set1); // 输出: Intersection: [2, 3]

        // 并集
        set1.addAll(set2);
        System.out.println("Union: " + set1); // 输出: Union: [1, 2, 3, 4]

        // 差集
        set1.removeAll(set2);
        System.out.println("Difference: " + set1); // 输出: Difference: [1]
	}
}

4. 过滤元素

import java.util.HashSet;
import java.util.stream.Collectors;

public class FilterElementsExample {
    public static void main(String[] args) {
        HashSet<String> names = new HashSet<>();
        
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
        names.add("David");
        
        // 过滤以字母 'A' 开头的元素
        HashSet<String> filteredNames = names.stream()
            .filter(name -> name.startsWith("A"))
            .collect(Collectors.toCollection(HashSet::new));
            
        System.out.println(filteredNames); // 输出: [Alice]
    }
}

OTA(Over-The-Air)升级 OTA(Over-the-Air)是一种通过无线方式进行数据传输和更新的技术,通常用于电子设备(如智能手机、汽车、物联网设备等)的软件、固件或配置更新。OTA可以在设备与服务器之间进行远程传输,用户无需将设备接入电脑或进行有线操作。通过OTA,用户只需要通过Wi-Fi或移动网络连接,便能自动接收并安装最新的更新,而无需手动干预。OTA的优点是便捷和高效,能够确保设备随时保持最新状态,同时减少用户的操作负担。:如智能家居设备、路由器、汽车等硬件设备的固件更新。:确保设备上的应用保持最新版本。 阅读详情

相关推荐

立创EDA手动拼板实战:当自带功能不够用,如何用‘复制粘贴’搞定异形拼版与特殊布局

本文详细介绍了立创EDA手动拼板技术在异形拼版与特殊布局中的应用实战。通过CTRL+SHIFT+V等核心操作技巧,解决混合尺寸拼板、特殊间距需求等复杂场景,提升PCB设计效率与灵活性,特别适合需要高精度控制的射频电路和医疗设备项目。

weixin_31967485的博客 386

Java集合---HashSet的源码分析

http://www.cnblogs.com/ITtangtang/p/3948538.html

u013291972的博客 251

基于FPGA低频方波测量-频率与占空比

基于FPGA低频方波测量-频率与占空比

DRAXY的博客 6732

java hashset 源码_Java集合之HashSet源码分析

一、HashSet简介HashSet是Set接口典型实现,它按照Hash算法来存储集合中的元素,具有很好的存取和查找性能。主要具有以下特点:不保证set的迭代顺序HashSet不是同步的,如果多个线程同时访问一个HashSet,要通过代码来保证其同步集合元素值可以是null当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,...

weixin_39860755的博客 184

波束管理 Beam Management

Beam Management in 5G NR   波束管理,是5G NR中基于信道质量来动态选择每个UE和gNB之间以什么方向和频率的波束beam来进行通信。   背景   5G NR(New Radio)支持非常高的数据速率和更低的延迟。5G NR支持FR1和FR2频段,FR1为亚6 GHz(450至6000 MHz);FR2为毫米波段(24.25 GHz至52.6 GHz)。   由于毫米波频带使用非常高的频率,因此会导致传播损耗和其他损耗。为了补偿损失,在这种频率下定向通信是必不可少的。

最忆是江南的博客 5826

用Django框架+爬虫技术实现自动获取可画(Canva)团队会员资格的方法

可画(canva)是一个非常流行的在线平面设计平台,因为它无需专业训练和技能就可以利用其丰富的资源设计出美观、酷炫的作品,因而它受到了极其广泛的设计专业和非专业人群的喜爱本文介绍了一种方法,它采用Django网络框架与爬虫技术相结合,实时监控定时更新可画团队版免费邀请链接的网站页面,一旦链接有更新动作,第一时间获取相关信息,并直接加载这个有效的邀请链接,自动进入可画网站获得团队版使用资格。

hhyyqq的博客 2208

Java基础之Collections框架Set实现类HashSet及其源码分析

Java基础之Collections框架Set实现类HashSet及其源码分析HashSet简单使用HashSet源码分析 这个类实现了Set接口,由一个哈希表(实际上是一个HashMap实例,HashMap研究到了再说,哈哈)支持。它不能保证集合的迭代顺序;特别是,它不能保证顺序随时间保持不变。这个类允许空元素。 这个类为基本操作(添加、删除、包含和大小)提供恒定的时间性能,假设哈希函数将元素正确地分散在bucket中。遍历这个集合所需的时间与HashSet实例的大小(元素的数量)与支持HashMap实例

HQ DevJ的专栏 2712

提示词工程中的上下文隔离

已经进入context的prompt是没有办法让大模型真正的忘记的,但是可以通过prompt技巧强约束模型的后续推理中“不再使用、不再提及、不再引用”某部分提示词,这其实是一种行为抑制(behavior suppression),并不是删除。

Criss@陈磊 234

java hashset 源码_死磕 java集合之HashSet源码分析

问题(1)集合(Collection)和集合(Set)有什么区别?(2)HashSet怎么保证添加元素不重复?(3)HashSet是否允许null元素?(4)HashSet是有序的吗?(5)HashSet是同步的吗?(6)什么是fail-fast?简介集合,这个概念有点模糊。广义上来讲,java中的集合是指java.util包下面的容器类,包括和Collection及Map相关的所有类。中义上来讲...

weixin_29901515的博客 168

RoCEv2 (RDMA over Converged Ethernet) 技术详细介绍

本文深入解析RDMA over Converged Ethernet (RoCEv2)技术,该技术是AI时代算力网络的核心。文章从四个维度展开:首先阐述RDMA如何通过零拷贝和内核旁路解决传统网络的数据搬运瓶颈;接着拆解RoCEv2协议栈,对比其与InfiniBand和iWARP的特性差异;然后分析其在分布式AI训练、高性能存储等场景的关键价值;最后提供实战指南,强调无损网络配置、流量隔离和精细监控的重要性。RoCEv2虽能带来微秒级延迟和极低CPU开销,但需精心设计网络环境才能发挥最大效能。

技术引领业务创新 1389

29、集成电路测试技术解析

本文深入解析了集成电路测试技术,涵盖定制电路测试资源与策略、混合模拟/数字电路测试方法、数字测试模式生成难点与解决方案,以及可控性和可观测性的核心概念。同时详细讨论了固定故障、桥接故障和开路故障等主要故障模型及其检测方法。在测试技术的综合应用与优化方面,提出了合理配置测试资源、优化测试模式和设计测试流程的策略。最后展望了测试技术的发展趋势,包括集成化测试、自动化测试和智能化测试。通过全面掌握这些测试技术,可以有效提高集成电路的质量和可靠性,推动集成电路产业的发展。

work3的博客 204

【Java容器源码】HashSet 源码分析

看源码先看类注释上,我们可以得到的信息有: 底层实现基于 HashMap,所以迭代时不能保证按照插入顺序,或者其它顺序进行迭代; add、remove、contanins、size 等方法的耗时性能,是不会随着数据量的增加而增加的,这个主要跟 HashMap 底层的数组数据结构有关,不管数据量多大,不考虑 hash 冲突的情况下,时间复杂度都是 O (1); 线程不安全的,如果需要安全请自行加锁,或者使用 Collections.synchronizedSet; 迭代过程中,如果数据结构被改变,会快速失败

A minor 2867

基于 Simulink 的飞轮储能系统(Flywheel Energy Storage System, FESS)充放电协调控制实战教程

本教程详细介绍了基于Simulink的飞轮储能系统(FESS)建模与控制方法。系统采用永磁同步电机(PMSM)和背靠背变流器架构,包含机侧全速域矢量控制和网侧直流稳压控制。重点讲解了机电耦合建模、FOC控制算法实现、基于电压下垂的协调控制策略,以及混合储能系统设计思路。教程提供了MATLAB函数代码示例,并给出典型工况下的仿真波形分析指南,同时指出了常见问题解决方案。该模型可用于研究飞轮储能在调频、能量回收等场景的应用,为新能源消纳和微网稳定提供仿真工具。

MHD0815的博客 166

Java HashSet源码分析

本文分析了Java HashSet的源码实现。HashSet基于HashMap实现,利用其key唯一性保证元素不重复。核心属性包括存储数据的HashMap和统一的value占位对象PRESENT。HashSet通过构造函数初始化底层HashMap,主要方法如add()、remove()、contains()等均委托给HashMap实现。add()方法通过判断put()返回是否为null来确定是否添加成功,remove()则通过比较返回值是否为PRESENT判断删除结果。其他方法如size()、isEmpty

xiangxiongfly 57

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

JAVA深化篇_20—— 面试必问之 HashSet的源码分析AV

HashSet底层源码分析

guojiaqi_的博客 121

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

java HashSet源码分析

上一篇集合中写到 Set是一个无序列表,不可重复,需要重写equals和hashCode方法 HashSet实现了Set接口,它不保证set 的迭代顺序,且不保证其顺序永久不变,允许为null空值。 继承AbstractSet接口,实现Set接口,克隆,序列化 Set<E>, Cloneable, java.io.Serializable AbstractSet官方解释: ...

来杯Java 330

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java集合之HashSet源码分析

一、HashSet简介   HashSet是Set接口典型实现,它按照Hash算法来存储集合中的元素,具有很好的存取和查找性能。主要具有以下特点: 不保证set的迭代顺序 HashSet不是同步的,如果多个线程同时访问一个HashSet,要通过代码来保证其同步 集合元素值可以是null   当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方...

weixin_34009794的博客 79

【Java集合源码】HashSet源码分析

HashSet 1,HashSet 概念 HashSet 是 Set 子接口的一个实现子类,它的底层由 HashMap 提供(数组+链表+红黑树),并借助 HashMap 的键来存储对象。由于是 Set 的实现子类,它具备 set 的无序、不可重复、非同步的特点;同时,由于 Hash 效果,它的查找会更快。 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneab

林立可 434

《Java源码分析》:HashSet

《Java源码分析》:HashSet前面几篇把Map、List相关的的几个类看了下,当然Set接口相关的类也相当的重要,我们也用的比较多,因此,我们也需要了解下Set接口的两个实现类HashSet、TreeSet的源码。这篇博文是记录HashSet的源码分析。下篇博文就来记录TreeSet的源码分析。如果想了解其他的源码分析,可点击下面相对应的连接哈。HashMap类的源码分析在这里:http://

wojiushimogui的博客 1184

JAVA:hashset常用方法和源码分析

public static void main(String [] args){ /**hashset特点: * 1.继承关系 * public class HashSet&lt;E&gt; * extends AbstractSet&lt;E&gt; * implements Set&lt...

颠沛的小丸子 304

java源码分析之HashSet及LinkedHashSet

Java容器类的用途是“保存对象”,分为两类:Map——存储“键值对”组成的对象;Collection——存储独立元素。Collection又可以分为List和Set两大块。List保持元素的顺序,而Set不能有重复的元素。      本文分析Set中最常用的HashSet类,并简单介绍和对比LinkedHashSet。      首先对Set接口进行简要的说明。       存

jzhf2012的专栏 5602

JAVA集合Set之HashSet源码分析

1、概述 HashSet是Java集合的Set的实现类,实际上底层它是HashMap,Set是无序的、不可重的.其中无序的含义是:添加到集合中和取出顺序不一致.可以存放null,但是只可以存放一个null. 需要深入了解它,便要从成员变量、构造方法、主要方法深入 2、成员变量 static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map;

兮遥 446

从源码分析java容器之HashSet

HashSet 是一个没有重复元素的集合。 它是由HashMap实现的,不保证元素的顺序,而且HashSet允许使用 null 元素。 HashSet是非同步的,如果需要保证同步,则需要应该使用 Collections.synchronizedSet 方法来“包装” set。 HashSet通过iterator()返回的迭代器是fail-fast的

夏夜凉月 374

Java HashSet 源码分析

本文介绍了 Java 中 HashSet 的源码分析的相关内容。。。

Regino的博客 457

13.Java SDK源码分析系列笔记-HashSet

HashSet底层是通过HashMap实现的,value使用new Object()作为占位符。

ThinkerQAQ 379

Java_HashSet源码分析

3.在Java8中,如果一条链表的元素个数到达THEEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树),6.在Java8中,如果一条链表的元素个数到达THEEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树)5.如果有,调用equals 比较,如果相同,就放弃添加,如果不相同,则添加到最后(是挂在节点的next上)

2501_92828095的博客 954
上一篇: Fork_Join模式:分治和Work-Stealing的完美结合
下一篇: Java的LinkedHashMap 源码解析
全粘架构师
博客等级 码龄22年 236粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全粘架构师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值