一文搞懂HashSet类的底层实现原理

news2024/11/15 12:21:32

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

哈喽,各位小伙伴们,你们好呀,我是喵手。

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在 Java 中,集合是非常重要的一部分,它们可以简化代码编写,提高代码效率。Java 提供了许多集合类,其中 HashSet 类是一种非常常用的集合类。本文将对 HashSet 类进行详细介绍。

摘要

本文将对 Java 中的 HashSet 类进行介绍。首先,我们将介绍 HashSet 类的简介和源代码解析,然后提供一些实际应用场景案例。接着,我们将对 HashSet 类的优缺点进行分析,以及类代码方法的介绍。最后,我们会提供一些测试用例,全文小结和总结。

HashSet类

简介

HashSet 类是 Java 中的一种集合类,它继承了 AbstractSet 类,实现了 Set 接口。HashSet 类可以存储不同类型的数据,而且元素是无序的,元素的值可以为 null。在 HashSet 中,每个元素都必须是唯一的,并且它们是通过哈希表存储的。HashSet 类使用哈希算法来计算元素的索引位置。

HashSet 类有以下几个重要的方法:

  • add(Object obj):将元素添加到集合中。
  • clear():清空集合中的所有元素。
  • contains(Object obj):判断集合中是否包含指定的元素。
  • isEmpty():判断集合是否为空集。
  • remove(Object obj):从集合中删除指定的元素。
  • size():返回集合中的元素个数。

源代码解析

HashSet 类的源代码解析可以分为以下几个部分:

  • 成员变量
  • 构造方法
  • 类方法

成员变量

HashSet 类的成员变量如下:

// 存储元素的哈希表
private transient HashMap<E,Object> map;

// 存储创建 HashSet 时指定的默认大小(容量为16)和负载因子(0.75)
private static final Object PRESENT = new Object();

其中,map 变量存储了 HashSet 中的所有元素,这些元素是存储在一个哈希表中的。PRESENT 变量存储了一个 Object 对象,该对象在向 HashSet 中添加元素时使用。

在这里插入图片描述

构造方法

HashSet 类有多个构造方法:

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);
}

这些构造方法可以根据不同的情况创建 HashSet 对象。例如,第一个构造方法创建默认的 HashSet 对象,第二个构造方法创建一个包含指定 Collection 中所有元素的 HashSet 对象。

在这里插入图片描述

类方法

HashSet 类的常用方法如下:

// 添加元素
public boolean add(E e)

// 移除元素
public boolean remove(Object o)

// 返回集合的大小
public int size()

// 清空集合
public void clear()

// 判断集合是否包含指定元素
public boolean contains(Object o)

在这里插入图片描述

应用场景案例

HashSet 类在实际开发中具有广泛的应用场景。下面是一些常见的场景。

去除重复元素

HashSet 类中的元素是唯一的,因此可以用于去除 List 中的重复元素。

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 2, 3, 4, 5, 4, 5));
Set<Integer> set = new HashSet<>(list);
list.clear();
list.addAll(set);
System.out.println(list); // [1, 2, 3, 4, 5]

判断集合是否包含指定元素

在 HashSet 中,可以使用 contains 方法来判断集合是否包含指定元素。

Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
System.out.println(set.contains(3)); // true
System.out.println(set.contains(6)); // false

去除空元素

HashSet 类中可以存储空元素,因此可以用于去除 List 中的空元素。

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "", "c", ""));
Set<String> set = new HashSet<>(list);
set.remove("");
list.clear();
list.addAll(set);
System.out.println(list); // [a, b, c]

优缺点分析

优点

  • 可以存储不同类型的数据。
  • 元素是无序的。
  • 可以存储空元素。
  • 具有去重功能。

缺点

  • 查找元素的速度较慢。
  • 当元素较多时,可能会消耗较大的内存空间。

类代码方法介绍

除了上述常用方法之外,HashSet 类还有一些常见的方法。

// 返回集合中的所有元素
public Iterator<E> iterator()

// 将集合转换为数组
public <T> T[] toArray(T[] a)

// 返回集合的哈希码
public int hashCode()

// 比较两个集合是否相等
public boolean equals(Object o)

// 返回集合的字符串表示形式
public String toString()

// 添加元素
public boolean addAll(Collection<? extends E> c)

// 移除所有元素
public boolean removeAll(Collection<?> c)

// 保留集合中与指定集合的交集
public boolean retainAll(Collection<?> c)

// 判断集合是否包含指定集合中的所有元素
public boolean containsAll(Collection<?> c)

// 将集合转换为流
public Stream<E> stream()

// 将集合转换为并行流
public Stream<E> parallelStream()

拓展:

这是Java集合框架中Collection接口中的一些常用方法,分别实现了以下功能:

  1. iterator():返回集合中的所有元素的迭代器。
  2. toArray(T[] a):将集合转换为指定类型的数组。
  3. hashCode():返回集合的哈希码。
  4. equals(Object o):比较两个集合是否相等。
  5. toString():返回集合的字符串表示形式。
  6. addAll(Collection<? extends E> c):向集合中添加指定集合中的所有元素。
  7. removeAll(Collection<?> c):移除集合中与指定集合相同的元素。
  8. retainAll(Collection<?> c):移除集合中与指定集合不同的元素,保留与指定集合相同的元素。
  9. containsAll(Collection<?> c):判断集合是否包含指定集合中的所有元素。
  10. stream():将集合转换为流。
  11. parallelStream():将集合转换为并行流。

这些方法可以方便地对Java集合进行操作和处理。

测试用例

下面是一些针对 HashSet 类的测试用例。

测试代码演示

package com.example.javase.se.classes;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @Author ms
 * @Date 2023-11-02 22:36
 */
public class HashSetTest {

    public static void main(String[] args) {
        Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
        System.out.println("set1 size: " + set1.size());

        Set<Integer> set2 = new HashSet<>(Arrays.asList(1, 2, 3));
        System.out.println("set2 add(4): " + set2.add(4));
        System.out.println("set2 add(3): " + set2.add(3));

        Set<Integer> set3 = new HashSet<>(Arrays.asList(1, 2, 3));
        System.out.println("set3 remove(1): " + set3.remove(1));
        System.out.println("set3 remove(4): " + set3.remove(4));

        Set<Integer> set4 = new HashSet<>(Arrays.asList(1, 2, 3));
        System.out.println("set4 contains(2): " + set4.contains(2));
        System.out.println("set4 contains(4): " + set4.contains(4));

        Set<Integer> set5 = new HashSet<>(Arrays.asList(1, 2, 3));
        set5.clear();
        System.out.println("set5 isEmpty: " + set5.isEmpty());
    }
}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

这是一个测试 HashSet 的程序,具体分析如下:

  1. 创建 HashSet 对象 set1,并添加元素 1、2、3、4、5,输出 set1 的大小。

  2. 创建 HashSet 对象 set2,并添加元素 1、2、3,尝试添加元素 4 和 3,输出添加结果。

  3. 创建 HashSet 对象 set3,并添加元素 1、2、3,尝试移除元素 1 和 4,输出移除结果。

  4. 创建 HashSet 对象 set4,并添加元素 1、2、3,尝试判断元素 2 和 4 是否存在,输出判断结果。

  5. 创建 HashSet 对象 set5,并添加元素 1、2、3,清空 set5,判断 set5 是否为空,输出判断结果。

以上操作都是使用 Set 接口中的方法进行的,具体来说:

  • 使用 HashSet 的构造方法,可以使用 Arrays.asList() 方法将数组转换成集合,从而快速添加元素。
  • add() 方法返回一个布尔值,表示添加元素的结果。当元素已存在时,不会再次添加,并且返回 false。
  • remove() 方法返回一个布尔值,表示移除元素的结果。当元素不存在时,不会进行移除,并且返回 false。
  • contains() 方法返回一个布尔值,表示集合中是否包含指定元素。
  • clear() 方法可以清空集合中的所有元素,使其成为空集合。
  • isEmpty() 方法可以判断集合是否为空,返回一个布尔值。

总体来说,HashSet 是一种基于哈希表实现的集合,具有快速添加、移除、判断元素是否存在的优势,同时不保证元素的顺序。

优点

  • 可以存储不同类型的数据。
  • 元素是无序的。
  • 可以存储空元素。
  • 具有去重功能。

缺点

  • 查找元素的速度较慢。
  • 当元素较多时,可能会消耗较大的内存空间。

小结

HashSet 类是 Java 中的一种集合类,它可用于存储不同类型的数据,元素是无序的,元素的值可以为 null。HashSet 类可以去除重复元素,具有去重功能。HashSet 类的优缺点如下:

总结

HashSet 类在 Java 中是一个非常实用的集合类。它可以用于存储不同类型的数据,并且具有去重功能。在实际开发中,我们可以使用 HashSet 类来去除 List 中的重复元素、判断集合中是否包含指定元素等等。但是需要注意的是,当元素较多时,可能会消耗较大的内存空间,因此在使用 HashSet 类时需要谨慎考虑。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1685414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flask多线程开发指南

文章目录 1. 什么是多线程&#xff1f;2. Flask中的多线程3. 注意事项结论 在Web应用程序开发中&#xff0c;有时候需要处理一些耗时的任务&#xff0c;例如与数据库交互、发送网络请求或执行计算密集型的操作。为了保持用户体验的流畅性&#xff0c;我们可以使用多线程来处理这…

【开源可视化报表设计器】借力实现高效率流程化办公!

进行数字化转型、实现流程化办公&#xff0c;这些应该是目前很多企业都想要实现的目标吧。那么&#xff0c;利用什么样的软件平台可以实现&#xff1f;低代码技术平台拥有可视化界面、灵活操作、好维护等众多优势特点&#xff0c;可以借助低代码技术平台、开源可视化报表设计器…

Hidedump:dumplsass加密免杀工具

文章目录 前记hook WriteAllduplication其他思路SilentProcessExitminidumpCallback 后记referencereference 前记 思路&#xff1a;直接dumplsass原文会被杀软删掉&#xff0c;通过hook WriteAll对dump的内容先加密再保存到磁盘并离线解密 项目已开源&#xff0c;该项目采用…

【git】开发提交规范(feat、fix、perf)

这段时间收到的需求很多&#xff0c;可能是临近两周一次的大版本灰度上线&#xff0c;这次产生了一个关于git的思考&#xff0c;就是各个版本之间怎么管理的问题&#xff0c;这里做出我自己的一些方法。 首先&#xff0c;既然已经明确了remote分支中的release分支为主分支&…

为什么说 Redis 是单线程的?——Java全栈知识(25)

为什么说 Redis 是单线程的&#xff1f; 我们常说的 Redis 是单线程的&#xff0c;但是我前面在讲持久化机制的时候又说 RDB 的持久化是通过主进程 fork 出一个子进程来实现 RDB 持久化。那么 Redis 到底是多线程还是单线程的呢&#xff1f; Redis 的网络 IO 和键值的读写是单…

爬虫学习--11.MySQL数据库的基本操作(上)

MySQL数据库的基本操作 创建数据库 我们可以在登陆 MySQL 服务后&#xff0c;使用命令创建数据库&#xff0c;语法如下: CREATE DATABASE 数据库名; 显示所有的数据库 show databases; 删除数据库 使用普通用户登陆 MySQL 服务器&#xff0c;你可能需要特定的权限来创建或者删…

java中的StringBuffer类和StringBuildet类

一、StringBuffer类 1、特点 底层是不被final修饰的char数组value,数组地址可以发生改变&#xff0c;当StringBuffer类对象的值发生改变时不用创建新的对象 2、构造方法 3、扩容规则 StringBuffer的底层数组value在扩容时为当前数组的长度2倍加2或者当前数组长度加上要追加…

CVE-2020-7982 OpenWrt 远程命令执行漏洞学习(更新中)

OpenWrt是一款应用于嵌入式设备如路由器等的Linux操作系统。类似于kali等linux系统中的apt-get等&#xff0c;该系统中下载应用使用的是opgk工具&#xff0c;其通过非加密的HTTP连接来下载应用。但是其下载的应用使用了SHA256sum哈希值来进行检验&#xff0c;所以将下载到的数据…

如何将短信从 iPhone 传输到计算机 - 5 种灵活的方式

概括 与他人交流的多种方式之一是发送短信。对于那些包含珍贵回忆或重要信息的消息&#xff0c;您需要将它们发送到另一台设备&#xff08;例如计算机&#xff09;进行备份。将短信文件发送到计算机是保存宝贵数据的最佳方法之一。继续阅读本文&#xff0c;了解如何将短信从 i…

深度学习 | 复杂注意力神经网络 —— 大模型

前面讲解了注意力神经网络 一、BERT模型 1、什么是BERT 它是由谷歌在2018年提出的 双向Transformer 编码器模型。 Bidirectional Encoder Representations from Transformers. 主要使用了Transformer的编码器 Transformer 编码器堆叠&#xff1b; 预训练 精调两步结构。 BERT…

FreeBSD/Linux下的系统资源监视器排队队

bpytop bpytop 是一个基于 Python 的资源监视器&#xff0c;可以在 FreeBSD 上使用。它提供了对文件写入磁盘、网络、CPU 和内存占用的监视功能。 pkg install bpytop 或者用ports安装 cd /usr/ports/sysutils/bpytop/ make install clean bashtop bashtop 也是一个基于 P…

微服务如何做好监控

大家好&#xff0c;我是苍何。 在脉脉上看到这条帖子&#xff0c;说阿里 P8 因为上面 P9 斗争失败走人&#xff0c;以超龄 35 被裁&#xff0c;Boss 上找工作半年&#xff0c;到现在还处于失业中。 看了下沟通记录&#xff0c; 沟通了 1000 多次&#xff0c;但没有一个邀请投递…

AI网络爬虫:批量爬取电视猫上面的《庆余年》分集剧情

电视猫上面有《庆余年》分集剧情&#xff0c;如何批量爬取下来呢&#xff1f; 先找到每集的链接地址&#xff0c;都在这个class"epipage clear"的div标签里面的li标签下面的a标签里面&#xff1a; <a href"/drama/Yy0wHDA/episode">1</a> 这个…

Redis篇 浅谈分布式系统

分布式系统 一. 单机架构二.分布式系统引入三.引入更多的应用服务器四.读写分离五.引入缓存服务器六. 将数据库服务器拆分七.微服务架构 一. 单机架构 单机架构,就是用一台服务器,完成所有的工作. 这时候就需要我们引入分布式系统了. 分布式系统是什么含义呢?就是由一台主机服…

Webpack源码泄露到Vue快速入门

前言 1.webpack 源码泄露 1.1漏洞简介 1.2存在泄露的站点 1.3 如何判断是否存在漏洞 方法1: 方法2: 1.4.如何将js.map文件还原为项目文件 1. 4.1查看npm版本 1.4.2 安装reverse-sourcemap 1. 4.3.检查是否安装 ​1. 4.4 使用reverse-sourcemap进行js.map文件还原操作…

二、信号连接槽函数

需求&#xff1a;点击Button按钮&#xff08;下班&#xff09;&#xff0c;label显示淦饭 信号发出者&#xff1a;Button 发送的信号&#xff08;signals&#xff09;&#xff1a;被点击 信号接收者&#xff1a;label 信号的处理&#xff08;slots&#xff09;&#xff1a;显示…

Rocketmq集群再搭建

注意上面这个官方架构是 主从模式&#xff0c;还无法做到高可用&#xff0c;因为master节点宕机&#xff0c;从节点没法变成主节点&#xff0c;需要人工重启&#xff0c;够用了。 1. 先准备1台虚拟机&#xff0c;装好1台再克隆2台 根据上面的图&#xff0c;3台机器中有一台…

【再探】Java—泛型

Java 泛型本质是参数化类型&#xff0c;可以用在类、接口和方法的创建中。 1 “擦除式”泛型 Java的“擦除式”的泛型实现一直受到开发者的诟病。 “擦除式”的实现几乎只需要在Javac编译器上做出改进即可&#xff0c;不要改动字节码、虚拟机&#xff0c;也保证了以前没有使…

MVVM_MVVMLight架构

介绍 MVVMLight是一个实现MVVM模式的轻量级框架&#xff08;相对于Prism&#xff09;&#xff0c;能够更好的帮助我们开发WPF Windows Phone、Windows 8、SilverLight相关项目。 安装 在NuGet 工具箱上搜索MVVMLight进行下载 下载后它帮你生成ViewModel文件夹&#xff0c;里面…

深度学习之基于Tensorflow卷积神经网络脑肿瘤分类识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 脑肿瘤是医学领域的一个重要问题&#xff0c;对人类的健康构成了严重威胁。传统的脑肿瘤分类识别方法…