当前位置: 首页 > news >正文

【Java】—— 集合框架:Collection子接口:Set不同实现类的对比及使用(HashSet、LinkedHashSet、TreeSet)

目录

5. Collection子接口2:Set

5.1 Set接口概述

5.2 Set主要实现类:HashSet

5.2.1 HashSet概述

5.2.2 HashSet中添加元素的过程:

5.2.3 重写 hashCode() 方法的基本原则

5.2.4 重写equals()方法的基本原则

5.2.5 练习

5.3 Set实现类之二:LinkedHashSet

5.4 Set实现类之三:TreeSet

5.4.1 TreeSet概述


5. Collection子接口2:Set

5.1 Set接口概述

  • Set接口是Collection的子接口,Set接口相较于Collection接口没有提供额外的方法

  • Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。

  • Set集合支持的遍历方式和Collection集合一样:foreach和Iterator。

  • Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。

5.2 Set主要实现类:HashSet

5.2.1 HashSet概述
  • HashSet 是 Set 接口的主要实现类,大多数时候使用 Set 集合时都使用这个实现类。

  • HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存储、查找、删除性能。

  • HashSet 具有以下特点

    • 不能保证元素的排列顺序

    • HashSet 不是线程安全的

    • 集合元素可以是 null

  • HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法得到的哈希值相等,并且两个对象的 equals()方法返回值为true

  • 对于存放在Set容器中的对象,对应的类一定要重写hashCode()和equals(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。

  • HashSet集合中元素的无序性,不等同于随机性。这里的无序性与元素的添加位置有关。具体来说:我们在添加每一个元素到数组中时,具体的存储位置是由元素的hashCode()调用后返回的hash值决定的。导致在数组中每个元素不是依次紧密存放的,表现出一定的无序性。

5.2.2 HashSet中添加元素的过程:
  • 第1步:当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法得到该对象的 hashCode值,然后根据 hashCode值,通过某个散列函数决定该对象在 HashSet 底层数组中的存储位置。

  • 第2步:如果要在数组中存储的位置上没有元素,则直接添加成功。

  • 第3步:如果要在数组中存储的位置上有元素,则继续比较:

    • 如果两个元素的hashCode值不相等,则添加成功;

    • 如果两个元素的hashCode()值相等,则会继续调用equals()方法:

      • 如果equals()方法结果为false,则添加成功。

      • 如果equals()方法结果为true,则添加失败。

    第2步添加成功,元素会保存在底层数组中。

    第3步两种添加成功的操作,由于该底层数组的位置已经有元素了,则会通过链表的方式继续链接,存储。

5.2.3 重写 hashCode() 方法的基本原则
  • 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。

  • 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。

  • 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。

注意:如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。

5.2.4 重写equals()方法的基本原则
  • 重写equals方法的时候一般都需要同时复写hashCode方法。通常参与计算hashCode的对象的属性也应该参与到equals()中进行计算。

  • 推荐:开发中直接调用Eclipse/IDEA里的快捷键自动重写equals()和hashCode()方法即可

    • 为什么用Eclipse/IDEA复写hashCode方法,有31这个数字?

首先,选择系数的时候要选择尽量大的系数。因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。(减少冲突)

其次,31只占用5bits,相乘造成数据溢出的概率较小。

再次,31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化。(提高算法效率)

最后,31是一个素数,素数作用就是如果我用一个数字来乘以这个素数,那么最终出来的结果只能被素数本身和被乘数还有1来整除!(减少冲突)

5.2.5 练习

练习1:在List内去除重复数字值,要求尽量简单

public static List duplicateList(List list) {HashSet set = new HashSet();set.addAll(list);return new ArrayList(set);
}
public static void main(String[] args) {List list = new ArrayList();list.add(new Integer(1));list.add(new Integer(2));list.add(new Integer(2));list.add(new Integer(4));list.add(new Integer(4));List list2 = duplicateList(list);for (Object integer : list2) {System.out.println(integer);}
}

练习2:获取随机数

        编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。

public class RandomValueTest {public static void main(String[] args) {HashSet hs = new HashSet(); // 创建集合对象Random r = new Random();while (hs.size() < 10) {int num = r.nextInt(20) + 1; // 生成1到20的随机数hs.add(num);}for (Integer integer : hs) { // 遍历集合System.out.println(integer); // 打印每一个元素}}
}

练习3:去重

        使用Scanner从键盘读取一行输入,去掉其中重复字符,打印出不同的那些字符。比如:aaaabbbcccddd

public class DistinctTest {public static void main(String[] args) {Scanner sc = new Scanner(System.in); // 创建键盘录入对象System.out.println("请输入一行字符串:");String line = sc.nextLine(); // 将键盘录入的字符串存储在line中char[] arr = line.toCharArray(); // 将字符串转换成字符数组HashSet hs = new HashSet(); // 创建HashSet集合对象for (Object c : arr) { // 遍历字符数组hs.add(c); // 将字符数组中的字符添加到集合中}for (Object ch : hs) { // 遍历集合System.out.print(ch);}}
}

5.3 Set实现类之二:LinkedHashSet

  • LinkedHashSet 是 HashSet 的子类,不允许集合元素重复。

  • LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以添加顺序保存的。

  • LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。

5.4 Set实现类之三:TreeSet

5.4.1 TreeSet概述
  • TreeSet 是 SortedSet 接口的实现类,TreeSet 可以按照添加的元素的指定的属性的大小顺序进行遍历。

  • TreeSet底层使用红黑树结构存储数据

  • 新增的方法如下: (了解)

    • Comparator comparator()

    • Object first()

    • Object last()

    • Object lower(Object e)

    • Object higher(Object e)

    • SortedSet subSet(fromElement, toElement)

    • SortedSet headSet(toElement)

    • SortedSet tailSet(fromElement)

  • TreeSet特点:不允许重复、实现排序(自然排序或定制排序)

  • TreeSet 两种排序方法:自然排序定制排序。默认情况下,TreeSet 采用自然排序。

    • 自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。

      • 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。

      • 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。

    • 定制排序:如果元素所属的类没有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。

      • 利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

      • 要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。

  • 因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象

  • 对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 或compare(Object o1,Object o2)方法比较返回值。返回值为0,则认为两个对象相等。

相关文章:

【Java】—— 集合框架:Collection子接口:Set不同实现类的对比及使用(HashSet、LinkedHashSet、TreeSet)

目录 5. Collection子接口2&#xff1a;Set 5.1 Set接口概述 5.2 Set主要实现类&#xff1a;HashSet 5.2.1 HashSet概述 5.2.2 HashSet中添加元素的过程&#xff1a; 5.2.3 重写 hashCode() 方法的基本原则 5.2.4 重写equals()方法的基本原则 5.2.5 练习 5.3 Set实现类…...

android Activity生命周期

android 中一个 activity 在其生命周期中会经历多种状态。 您可以使用一系列回调来处理状态之间的转换。下面我们来介绍这些回调。 onCreate&#xff08;创建阶段&#xff09; 初始化组件&#xff1a;在这个阶段&#xff0c;Activity的主要工作是进行初始化操作。这包括为Ac…...

C#的面向对象

1&#xff09;对象 算法数据结构 2&#xff09;对象的行为已方法的形式定义的&#xff0c;属性以成员变量的形式定义的 面向对象程序设计的特点 1&#xff09;封装性 2&#xff09;继承性 3&#xff09;多态性 知识点&#xff1a; 封装性面向对象的核心思想&#xff0c;将…...

【区别】三种命令取消已暂存的文件,处理暂存区和文件的跟踪状态

取消已暂存的文件 git restore --staged <文件>、git reset HEAD <文件> 和 git rm --cached <文件> 都可以用于取消已暂存的文件&#xff0c;但它们的作用和使用场景略有不同。下面是它们的区别&#xff1a; 1. git restore --staged <文件> 该命令…...

如何在Spring Boot中有条件地运行CommandLineRunner Bean

PS 使用 Spring Boot 3.1.2 进行测试 1.使用ConditionalOnProperty ConditionalOnProperty仅当特定属性存在或具有特定值时&#xff0c;注释才会创建 Bean 。 在此示例中&#xff0c;仅当或文件中的CommandLineRunner属性db.init.enabled设置为 true时&#xff0c;才会执行。…...

边缘自适应粒子滤波(Edge-Adaptive Particle Filter)的MATLAB函数示例,以及相应的讲解

目录 讲解 初始化 预测步骤 观测模拟 权重更新 重采样 状态估计 总结 下面是一个简单的边缘自适应粒子滤波&#xff08;&#xff09;的函数示例&#xff0c;以及相应的讲解。 程序源代码&#xff1a; function X_est edgeAdaptiveParticleFilter(numParticles, numS…...

一块1T硬盘怎么有sdb1和sdb2

在一块 1TB 硬盘上看到两个分区 sdb1 和 sdb2 是非常常见的现象。硬盘可以被划分为多个分区&#xff0c;每个分区都可以用作不同的目的&#xff0c;如存储不同类型的数据、安装不同的操作系统或为系统不同的功能提供支持。 1. 分区的概念 硬盘可以被划分为多个分区&#xff0…...

Python知识点:如何使用Flink与Python进行实时数据处理

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 如何使用Flink与Python进行实时数据处理 Apache Flink是一个流处理框架&#xf…...

Swagger配置且添加小锁(asp.net)(笔记)

此博客是基于 asp.net core web api(.net core3.1)框架进行操作的。 一、安装Swagger包 在 NuGet程序包管理中安装下面的两个包&#xff1a; swagger包&#xff1a;Swashbuckle.AspNetCore swagger包过滤器&#xff1a;Swashbuckle.AspNetCore.Filters 二、swagger注册 在…...

lambda表达式底层实现:反编译LambdaMetafactory + 转储dump + 运行过程 + 反汇编 + 动态指令invokedynamic

一、结论先行 lambda 底层实现机制 1.lambda 表达式的本质&#xff1a;函数式接口的匿名子类的匿名对象 2.lambda表达式是语法糖 语法糖&#xff1a;编码时是lambda简洁的表达式&#xff0c;在字节码期&#xff0c;语法糖会被转换为实际复杂的实现方式&#xff0c;含义不变&am…...

Unity初识+面板介绍

Unity版本使用 小版本号高&#xff0c;出现bug可能性更小&#xff1b;一台电脑可以安装多个版本的Unity&#xff0c;但是需要安装在不同路径&#xff1b;安装Unity时不能有中文路径&#xff1b;Unity项目路径也不要有中文。 Scene面板 相当于拍电影的片场&#xff0c;Unity程…...

【CSS in Depth 2 精译_041】6.4 CSS 中的堆叠上下文与 z-index(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09;第二章 相对单位&#xff08;已完结&#xff09;第三章 文档流与盒模型&#xff08;已完结&#xff09;第四章 Flexbox 布局&#xff08;已…...

uniapp微信小程序巧用跳转封装鉴权路由

1.这是封装的跳转方法&#xff1a; import store from "../stores/store";function Router(type, url, params) {const NoLoginPage [。。。。。];var queryString Object.keys(params).map((key) > ${key}${params[key]}).join("&");if (!NoLog…...

国外电商系统开发-运维系统开发

因项目运营环境在国外&#xff0c;所以必须将服务器选择国外&#xff0c;加上第一次运营国外项目。在两大趋势下&#xff0c;企业的运营方向必须通过大数据来分析及修正运营方向&#xff0c;加上后期服务器数量日益增多&#xff0c;如何有效的管理众多的服务器及验证运营方向&a…...

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…...

【艾思科蓝】机器学习框架终极指南:PyTorch vs TensorFlow vs Keras vs Scikit-learn

第十届建筑、土木与水利工程国际学术会议(ICACHE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看&#xff1a;学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 1. PyTorch PyTorch的特点 PyTorch的用例 PyTorch的安装 PyTorch代码示例 2. TensorFlow …...

招联金融秋招内推2025

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…...

遮罩解决图片悬浮操作看不到的情况

未悬浮效果 悬浮效果 如果仅仅是添加绝对定位&#xff0c;那么遇到白色图片&#xff0c;就会看不到白色字体。通过遮罩&#xff08;绝对定位透明度&#xff09;就可以解决这个问题。 <script setup> </script><template><div class"box"><…...

IoT网关的主要功能有哪些?天拓四方

在数字化浪潮席卷全球的今天&#xff0c;物联网&#xff08;IoT&#xff09;技术凭借其独特的优势&#xff0c;逐渐在各个领域展现出强大的生命力。而IoT网关&#xff0c;作为连接物理世界与数字世界的桥梁&#xff0c;其在物联网体系中的作用愈发凸显。 一、数据聚合与预处理…...

继承实现单例模式的探索(一)

前言 之前看到朋友采用继承的方式来实现单例模式&#xff0c;觉得很厉害&#xff0c;随后自己去探索了一番&#xff0c;以前实现单例模式都是把代码内联到具体的类中&#xff0c;这使得工程中每次需要使用单例模式时&#xff0c;都采用拷贝的方式&#xff0c;增加了很多冗余代码…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...