Set集合的特点以及唯一性原理(如何保证元素不可重复)

news/2024/4/19 14:35:11/文章来源:https://blog.csdn.net/miachen520/article/details/130351885

Set集合是Collection集合的子接口,它有三个常用子类:

1.HashSet:底层结构是哈希表。无序(新增顺序和获取顺序不一定一致)。

2.LinkedHashSet:哈希表+链表。有序。

3.TreeSet<E>:红黑树。可排序的

一、HashSet

底层原理是Hash表实现的,存储元素的顺序不是按照存入的顺序,而是按照哈希值来存取数据(无序),哈希值通过hashcode方法获取。判断两个元素是否相等时,首先比较两个元素的哈希值是否相等,再比较equals方法,如果返回的是true,则两个元素对象相等,视为同一个元素。所以,HashSet添加一个元素时,当哈希值相同,equals为false时,添加的元素在相同的哈希值下顺延,即存一列(放在同一个哈希桶中);当哈希值不同,equals返回true时,也会存入到不同哈希值下并添加成功;都相同时则视为同一元素,添加失败。同时,线程是不安全的。

二、LinkedHashSet

LinkedHashSet是HashSet的子类,也是根据hashcode的值来存储数据,不允许元素重复,使用时直接调用HashSet的方法,但是由于是基于LinkedHashMap实现的,以双向链表来维护插入元素的顺序,所以看起来是按照插入的顺序来存放的。

三、TreeSet

TreeSet底层采用的是红黑树存储数据,可以确保元素有排序的状态,所以此结构是有序的,查询速度较list更快。排序方式包括自然排序和定制排序。

自然排序

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

如Integer和String对象都可以进行默认的排序,但如果要添加一个元素,那么该元素的的类必须实现Comparable接口和compareTo方法。

定制排序

若元素所属的类没有实现Comparable接口,或不希望按照升序、降序的方式排列元素或按照其它属性大小进行排序,则可以使用定制排序,通过Comparator接口来实现,需要重写compare(T o1,T o2)方法,即利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

Set集合是如何保证元素不可重复

Set集合的特点如下:

1,元素无序

2,元素不可重复

那么Set集合底层是如何保证元素无序的呢?

1,在往Set集合中添加对象的时候,首先会通过该对象的hashCode方法计算该对象的hash值。

2,将计算出来的hash值去hash表中查询,如果hash表中不存在该值,则对象添加成功。如果hash表中有该hash值,那么还会将要添加的对象和集合中的对象进行进一步的比较,使用对象的equals方法比较对象的field,如果field也相同,则是重复的对象,该对象添加失败。如果equals返回的是false,则说明两个对象不是同一个对象。则该对象就会添加到已有对象链表的末尾。该种情况称为hash碰撞。

总结

Set集合是通过hashCode和equals方法来保证元素不可重复的。之所以先计算hashCode,是为了提高添加的效率。所以当自定义对象需要保存到Set集合中的时候,就需要重写以上两个方法。

重点:

 如果元素存储位置不为空,也就是已经有元素了,则会进行比较

 如果哈希值不同,说明新元素与旧元素不同,可以将新元素加入到集合中

 如果哈希值相同,则继续调用对象的equals方法进行比较

 如果equals方法比较的结果为false,说明两者不同,将新元素加入到集合中

 如果equals方法比较的结果为true,说明两者完全相同,不会添加新元素

重写hashCode方法时的原则:

保证同一个对象返回的hash值相同。

不同对象计算出来的hash值不同。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql设置表只存储一段时间的数据

使用MySQL的事件调度器&#xff08;Event Scheduler&#xff09;来定期删除表中的数据。 假设你要删除的表是mytable&#xff0c;并且表中有一个名为created_at的日期时间类型的列&#xff0c;存储了每条记录的创建时间。你可以通过以下步骤设置表只存储30天的数据&#xff1a…

机器学习 协同过滤算法

协同过滤算法 协同过滤算法是根据已有的数据来推测出未知的数据&#xff0c;从海量的数据中找到相似度达到指定范围的数据&#xff0c;而这些数据成为你的邻居&#xff0c;系统将会为你推荐心仪的物品。 余弦相似法 通过计算两个向量的夹角余弦值来评估它们的相似度 修正余弦…

《站在巨人的肩膀上学习Java》

Java从诞生距今已经有28年了&#xff0c;在这段时间里&#xff0c;随着Java版本的不断迭代&#xff0c;Java新特性的不断出现&#xff0c;使得Java被使用的越来越广泛。在工程界Java语言一直是大家最喜欢的语言之一&#xff0c;Java一直排行在编程语言热门程度的前3名。 可想而…

从0搭建Vue3组件库(六):前端流程化控制工具gulp的使用

随着前端诸如webpack&#xff0c;rollup&#xff0c;vite的发展&#xff0c;gulp感觉似乎好像被取代了。其实并没有&#xff0c;只不过它从台前退居到了幕后。我们仍然可以在很多项目中看到它的身影&#xff0c;比如elementplus、vant等。现在gulp更多的是做流程化的控制。 比如…

delta.io 参数 spark.databricks.delta.replaceWhere.constraintCheck.enabled

总结 默认值true 你写入的df分区字段必须全部符合覆盖条件 .option("replaceWhere", "c2 == 2") false: df1 overwrite tb1: df1中每个分区的处理逻辑: - tb1中存在(且谓词中匹配)的分区,则覆盖 - tb1中存在(谓词中不匹配)的分区,则append - tb1中不存…

今天试了试chatgpt

今天试了试chatgpt&#xff0c;真是服了 arcade&#xff1f; Arcade是一个Python游戏开发库&#xff0c;它提供了一系列的工具和函数&#xff0c;可以帮助开发者快速地创建2D游戏。以下是Arcade的一些特点&#xff1a; 简单易用&#xff1a;Arcade提供了简单易用的API&#x…

Android分屏流程分析

本文基于Android 11。 SystemUI模块中的Divider管理着所有关于分屏的对象&#xff1a; DividerView&#xff08;分屏分割线&#xff0c;分屏显示界面&#xff09;SplitScreenTaskOrganizer&#xff08;分屏Task组织者&#xff0c;分屏逻辑&#xff09; 这里重点关注分屏逻辑…

Qt如何生成dump文件和pdb文件并进行调试定位

在main文件中增加下面代码用于可生成dump文件 #include "widget.h" #include <QApplication> #include <QDir> #include <QDateTime> #ifdef Q_OS_WIN#include <windows.h>#include <dbghelp.h> #endifstatic LONG WINAPI exceptionC…

简单介绍一下什么是“工作内存”和“主内存”(JMM中的概念)

在学习Java多线程编程里&#xff0c; volatile 关键字保证内存可见性的要点时&#xff0c;看到网上有些资料是这么说的&#xff1a;线程修改一个变量&#xff0c;会把这个变量先从主内存读取到工作内存&#xff1b;然后修改工作内存中的值&#xff0c;最后再写回到主内存。 对…

Spring 循环依赖处理之三级缓存设计

一、思考 1、Spring是如何解决循环依赖问题的? 2、为什么要使用三级缓存?二级缓存能否解决问题? 3、提前暴露对象暴露的是什么? 4、主要源码 二、循环依赖 1、介绍 如上图&#xff0c;创建A之前需要先创建B,创建B之前需要先创建A,造成循环依赖。 由于A没创建完成&am…

一个关于Mybatis和spring的公共组件starter

utils-springboot-starter 介绍使用说明 介绍 一个关于Mybatis和spring的公共组件starter&#xff0c;目前包含以下功能&#xff1a; 接口请求日志SQL执行日志数据自动加解密数据自动脱敏服务治理方面&#xff1a; 接口限流接口熔断降级&#xff1a;CPU、内存、异常数、异常率…

win11 环境下streamlit使用pycharm debug

目录 1. pycharm中配置run 脚本2. streamlit3. 开始debug调试 1. pycharm中配置run 脚本 &#xff08;一&#xff09;点击 Edit Configurations,按图操作. 2. streamlit 1.streamlit 安装在 anaconda 的 base 环境&#xff08;随意哈&#xff0c;安装哪里都可以&#xff0c…

问题定位及解决方案

1.视频沉浸页快速滑动后&#xff0c;必现不能向下划动 复现步骤&#xff1a; 进入视频沉浸页&#xff0c;快速向下划动&#xff0c;滑动到第一页最后一个时&#xff0c;不能再向下划动。 解决步骤&#xff1a; 1.确定请求API&#xff1a; mtop.aliexpress.ugc.feed.video.lis…

PE文件反编译为python脚本流程

1、查壳 DetectltEasy、PeiD查壳 2、脱壳 常见打包工具PyInstaller&#xff0c;脱壳方法 &#xff08;1&#xff09;用pyinstxtractor.py脱壳&#xff0c;用”python pyinstxtractor.py 1.exe“命令&#xff0c;生成“.exe文件名_extracted” &#xff08;2&#xff09;用…

深度学习技巧应用8-各种数据类型的加载与处理,并输入神经网络进行训练

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下深度学习技巧应用8-各种数据类型的加载与处理&#xff0c;并输入神经网络进行训练。在模型训练中&#xff0c;大家往往对各种的数据类型比较难下手&#xff0c;对于非结构化数据已经复杂的数据的要进行特殊处理&…

LeetCode:6390. 滑动子数组的美丽值

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;6390. 滑动子数组的美丽值 题目描述&#xff1a;给你一个长度为 n 的整…

波形生成:均匀和非均匀时间向量

波形生成—— 脉冲、chirp、VCO、正弦函数、周期性/非周期性和调制信号 使用 chirp 生成线性、二次和对数 chirp。使用 square、rectpuls 和 sawtooth 创建方波、矩形波和三角形波。 如需了解此处未显示的其他无线波形生成功能&#xff0c;请参阅无线波形发生器 (Communicat…

完整的生产车间管理流程是怎样的?六大步骤分享

阅读本文您将了解&#xff1a;1.生产车间管理的特征&#xff1b;2.生产车间管理流程具体步骤&#xff1b;3.生产车间管理流程规范的重要性。 一、生产车间管理的特征 车间管理是指对车间所从事的各项生产经营活动进行计划、组织、指挥、协调和控制的一系列管理工作。生产车间…

巧用千寻位置GNSS软件| 电力线勘测如何实现?

正如大家所知&#xff0c;电力线勘测是在做电力线路设计之前对设计线路沿途自然环境进行勘察测量&#xff0c;最后把手簿测量数据在电脑端经过转换输出为电力软件专用格式数据的专用功能。 那么在千寻位置GNSS软件中该如何操作完成电力线的勘察测量呢&#xff1f; 点击【测量】…

SwiftUI 中 TabView 如何原生使用类 UIPageView 的翻页样式?

功能需求 我们知道 TabView 是 SwiftUI 中非常好用的布局组织容器,它可以分类组织视图并依次展示给用户。 从 SwiftUI 2.0 开始(iOS 14.0+),TabView 除了常规的以标签(Tab Label)样式显示外,还可以用类似 UIPageView 的样式分页原生显示视图,显得更加简洁: 如上图所…