HashSet及其实现原理

目录

    • 一、Set
    • 二、HashSet
    • 三、HashSet的实现原理
    • 四、HashSet的线程安全与顺序
      • 1、线程安全
      • 2、有序性

一、Set

    Set 接口是 java.util 包下的一个集合接口,它继承自 Collection 接口。Set 接口定义了一个不允许包含重复元素的集合。Set 接口的实现类主要有 HashSet、LinkedHashSet 和 TreeSet。

在这里插入图片描述

以下是 Set 接口的一些关键特性:

  1. 不包含重复元素:Set 接口的实现类不允许集合中存在两个相等的对象。
  2. 无序性:大多数 Set 实现(如 HashSet)不保证集合的迭代顺序;特别是它不保证该顺序恒久不变。
  3. 唯一性:Set 接口的 add 方法在添加元素时,如果集合中已经存在该元素,则不会再次添加。
  4. 可选的排序:某些 Set 实现(如 TreeSet)会根据其元素的自然顺序或者构造集合时所指定的比较器来对元素进行排序。

关键特性总结:无序不重复、可选排序

    
Set 接口定义了以下方法:

  • add(E e):添加元素,如果元素已存在则返回 false,否则添加后返回 true。
  • remove(Object o):如果集合中存在该元素,则移除它并返回 true,否则返回 false。
  • contains(Object o):检查集合是否包含指定元素。
  • size():返回集合中的元素数量。
  • isEmpty():检查集合是否为空。
  • clear():移除集合中的所有元素。
  • iterator():返回集合的迭代器。
        

二、HashSet

    HashSet 是 Java 集合框架中的一个非常常用的集合类,它是 java.util包的一部分。HashSet继承自 AbstractSet 类,实现了 Set接口。底层基于HashMap实现。只存储元素,不存储键值对,它不允许重复的元素。

private transient HashMap<E,Object> map;// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();/*** Constructs a new, empty set; the backing <tt>HashMap</tt> instance has* default initial capacity (16) and load factor (0.75).*/
public HashSet() {map = new HashMap<>();
}

以下是 HashSet 的一些关键特性:

  1. 不允许重复HashSet 不允许集合中有重复的元素。如果尝试添加一个已经存在的元素,HashSet 会保持原样,不会添加新元素。
  2. 无序HashSet 不保证元素的顺序,每次迭代集合时元素的顺序可能不同。
  3. 基于哈希表HashSet 内部使用 HashMap 实现,每个元素都作为 HashMap 的一个键,而对应的值是一个虚拟对象(通常是 HashSet 内部的一个静态对象)。
  4. 性能:由于 HashSet 基于哈希表,因此它在添加、删除和查找元素时通常提供常数时间的性能(即 O(1) 时间复杂度),但这取决于哈希函数的质量和冲突的数量。
  5. 不保证线程安全HashSet 不是线程安全的。如果需要线程安全的集合,可以使用 Collections.synchronizedSet(new HashSet<>()) 包装 HashSet,或者使用 ConcurrentHashMap 的键集。
  6. 可以包含 null 元素HashSet 允许包含一个 null 元素,因为 HashMap 允许 null 作为键。
  7. 迭代器HashSet 提供迭代器来遍历集合中的所有元素。

主要特性总结: 无序不重复,只存储元素不存储键值对,线程不安全。

    

三、HashSet的实现原理

HashSet 是 Java 中的一个集合类,它基于 HashMap实现。下面是 HashSet的实现原理:

  1. 基于 HashMap

    • HashSet 的内部实际上是使用一个 HashMap 来存储元素的。
    • 每个 HashSet 元素都作为 HashMap 的键,而对应的值是一个固定的虚拟对象(通常是一个静态的布尔值)。
  2. 元素唯一性

    • 由于 HashMap 的键是唯一的,所以 HashSet 能够保证元素的唯一性。
  3. 添加元素

    • 当你向 HashSet添加一个元素时,它实际上是将该元素作为键添加到内部的 HashMap 中。

    • 如果 HashMap 中已经存在这个键,则 HashSet 会认为元素已经存在,不会添加重复的元素。

      public boolean add(E e) {return map.put(e, PRESENT)==null;
      }
      
  4. 删除元素

    • 当你从 HashSet 删除一个元素时,它实际上是从内部的 HashMap 中删除对应的键。
  5. 查找元素

    • 当你检查 HashSet 是否包含某个元素时,它实际上是在内部的 HashMap 中查找这个键。
  6. 迭代器

    • HashSet 的迭代器实际上是迭代内部 HashMap 的键集。

      public Iterator<E> iterator() {return map.keySet().iterator();
      }
      
  7. 性能

    • HashSet 的添加、删除和查找操作的性能通常都是常数时间的(O(1)),这得益于 HashMap 的性能。
  8. 容量和加载因子

    • HashSet 继承了 HashMap 的容量和加载因子的概念,这些参数影响 HashSet 的性能和内存使用。
  9. 并发性

    • HashSet不是线程安全的。如果你需要线程安全的集合,可以使用 Collections.synchronizedSet(new HashSet<>(...)) 或者 ConcurrentHashMap 的键集。
  10. 序列化

    • HashSet 实现了 Serializable 接口,这意味着它可以被序列化和反序列化。

    

四、HashSet的线程安全与顺序

1、线程安全

HashSet 是非线程安全的。这意味着多个线程同时修改 HashSet可能会导致不可预知的行为。如果多个线程需要访问和修改同一个 HashSet实例,必须通过外部同步来确保线程安全。

如果你需要线程安全的 Set 集合,可以考虑以下替代方案:

  1. Collections.synchronizedSet:通过这个静态方法包装一个 HashSet,可以提供简单的线程安全。但是,这种方法的并发性能较低,因为每次访问都需要获取锁。

  2. ConcurrentHashMap 的 keySet 方法ConcurrentHashMap 提供了 keySet 方法,它返回一个线程安全的 Set 视图。这个 Set 支持更高效的并发访问。

  3. CopyOnWriteArraySet:这是一个线程安全的 Set 实现,它在每次修改(添加或删除元素)时都会复制整个底层数组。这种方法适用于读多写少的场景。

    import java.util.Collections;
    import java.util.Set;
    import java.util.concurrent.CopyOnWriteArraySet;public class ThreadSafeSetExample {public static void main(String[] args) {// 使用 Collections.synchronizedSet 包装 HashSetSet<String> syncSet = Collections.synchronizedSet(new HashSet<>());syncSet.add("Element1");syncSet.add("Element2");// 使用 CopyOnWriteArraySetSet<String> copyOnWriteSet = new CopyOnWriteArraySet<>();copyOnWriteSet.add("Element1");copyOnWriteSet.add("Element2");// 迭代两个线程安全的 SetSystem.out.println("Synchronized Set: " + syncSet);System.out.println("CopyOnWriteArraySet: " + copyOnWriteSet);}
    }
    

2、有序性

HashSet 不保证元素的顺序。它基于 HashMap实现,而 HashMap不保证键的顺序。因此,每次迭代 HashSet 时元素的顺序可能不同。

如果你需要一个有序的 Set 集合,你可以考虑以下几种方法:

  1. TreeSet: TreeSet 是一个有序的 Set集合,它基于红黑树实现。TreeSet可以确保元素处于排序状态,无论是按照自然顺序还是根据提供的 Comparator。

  2. LinkedHashSet: LinkedHashSet维护了元素的插入顺序,或者在构造时指定的最近期访问顺序。它内部使用 LinkedList 来维护元素的顺序,同时使用 HashMap 来保证元素的唯一性。

  3. 使用 HashSet 与额外的数据结构: 如果你需要保留 HashSet 的所有特性,并且只需要偶尔的顺序访问,你可以在需要的时候将 HashSet 元素添加到一个 TreeSet或 LinkedHashSet 中,进行排序操作。

    import java.util.HashSet;
    import java.util.Set;
    import java.util.stream.Collectors;public class OrderedSetExample {public static void main(String[] args) {Set<Integer> hashSet = new HashSet<>();hashSet.add(5);hashSet.add(1);hashSet.add(4);hashSet.add(2);// 仅在需要有序时进行排序Set<Integer> sortedSet = hashSet.stream().collect(Collectors.toCollection(TreeSet::new));for (Integer number : sortedSet) {System.out.println(number);}}
    }
    
  4. 自定义有序 Set实现: 如果你有特殊的排序需求,你可以创建自己的 Set 实现,继承 AbstractSet 类,并使用你选择的任何数据结构(如数组、链表等)来维护元素的顺序。

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

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

相关文章

【网络安全的神秘世界】ssrf服务端请求伪造

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 ssrf 一、SSRF原理及漏洞演示 1.1 漏洞简介 SSRF&#xff08;Server-Side Request Forgery&#xff1a;服务端请求伪造&am…

3分钟手把手教FL Studio 24.1.1.4285中文破解完整版安装激活图文教程

FL Studio 24.1.1.4285中文破解完整版首先提供了音符编辑器&#xff0c;编辑器可以针对作曲者的要求编辑出不同音律的节奏&#xff0c;例如鼓&#xff0c;镲&#xff0c;锣&#xff0c;钢琴&#xff0c;笛&#xff0c;大提琴&#xff0c;筝&#xff0c;扬琴等等任何乐器的节奏律…

十三,Spring Boot 中注入 Servlet,Filter,Listener

十三&#xff0c;Spring Boot 中注入 Servlet&#xff0c;Filter&#xff0c;Listener 文章目录 十三&#xff0c;Spring Boot 中注入 Servlet&#xff0c;Filter&#xff0c;Listener1. 基本介绍2. 第一种方式&#xff1a;使用注解方式注入&#xff1a;Servlet&#xff0c;Fil…

Linux——应用层自定义协议与序列化

目录 一应用层 1再谈 "协议" 2序列化与反序列化 3理解read,write,recv,send 4Udp vs Tcp 二网络版本计算器 三手写序列和反序列化 四进程间关系与守护进程 1进程组 1.1什么是进程组 1.2组长进程 2会话 2.1什么是会话 2.2会话下的前后台进程 3作业控…

基于Arduino Uno的简易可视化操作界面设计

Arduino UNO是基于ATmega328P的Arduino开发板。它有14个数字输入/输出引脚&#xff08;其中6个可用于PWM输出&#xff09;、6个模拟输入引脚&#xff0c;一个16 MHz的晶体振荡器&#xff0c;一个USB接口&#xff0c;一个DC接口&#xff0c;一个ICSP接口&#xff0c;一个复位按钮…

C++速通LeetCode简单第16题-买卖股票的最佳时机

思路要点&#xff1a;假设当天卖&#xff0c;动态更新最低价格和最大利益 class Solution { public://要点&#xff1a;假设当天卖&#xff0c;动态更新最低价格和最大利益int maxProfit(vector<int>& prices) {int ans 0;int lowest prices[0];for(int i 1; i &…

COMP 6714-Info Retrieval and Web Search笔记week1

哭了哭了&#xff0c;这周唯一能听懂的就这门 目录 IR&#xff08;Information Retrieval)是什么&#xff1f;IR的基本假设Unstructured (text) vs. structuredDocuments vs. Database Records比较文本&#xff08;Comparing Text&#xff09;IR的范围(Dimensions of IR)IR的任…

多线程1(游戏逆向)

#include<iostream> #include<windows.h> #include<tchar.h> #include<stdio.h> #include <process.h> #pragma warning(disable:4996) //exe应用程序 VOID PrintUI(CONST CHAR* ExeName, CONST CHAR* UIName, CONST CHAR* color, SHORT X坐标, …

基于SSM的银发在线教育云平台的设计与实现

需要项目源码请联系我&#xff0c;目前有各类成品 毕设 javaweb ssh ssm springboot等等项目框架&#xff0c;源码丰富。 专业团队&#xff0c;咨询就送开题报告&#xff0c;活动限时免费&#xff0c;有需要的朋友可以来留言咨询。 一、摘要 现在的科技进步使得人们的学习不仅…

C++面试常见手撕题目

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 分享常见的面试手撕…

CC2530实现按键控制LED

实现按钮控制LED1开启和关闭 1配置环境 2扩展资料 通用io和外设io 设置输入输出 设置输入模式 3实例代码 #include "ioCC2530.h"void delay(int n){int i,j;for(i0;i<n;i){for(j0;j<240;j){asm("NOP");asm("NOP");asm("NOP")…

在 Python 画图中同时设置中英文字体

前言 在使用matplotlib.pyplot画图时&#xff0c;默认情况下都是黑体字&#xff0c;很不美观。如果含有中文&#xff0c;可能无法显示&#xff1b;显示了中文之后英文字体就不能使用。本文针对这些问题逐一给出解决方案。 同时设置中英文字体 我们都知道&#xff0c;按照下面的…

8路模拟量采集模块,4~20mA 0~10V电流电压高速采集——DAM-3054P

阿尔泰科技 DAM-3054P为8路差分模拟量采集模块&#xff0c;高速采集&#xff0c;每通道采集速率为500sps&#xff0c;16位AD&#xff0c;支持RS485通讯接口&#xff0c;带有标准ModbusRTU协议。配备良好的人机交互界面&#xff0c;使用方便&#xff0c;性能稳定。 指标参数&…

Spring Boot母婴商城:安全、便捷、高效

2 相关技术 2.1 SSM框架介绍 本课题程序开发使用到的框架技术&#xff0c;英文名称缩写是SSM&#xff0c;在JavaWeb开发中使用的流行框架有SSH、SSM、SpringMVC等&#xff0c;作为一个课题程序采用SSH框架也可以&#xff0c;SSM框架也可以&#xff0c;SpringMVC也可以。SSH框架…

PSINS工具箱函数介绍——kfplot

关于工具箱 kfplot是图像绘制的函数,用于绘制关于滤波(前/后)的误差图像。 本文所述的代码需要基于PSINS工具箱,工具箱的讲解: PSINS初学指导:https://blog.csdn.net/callmeup/article/details/137087932使用方法 函数形式为: k f p l o t ( x k p k , v a r a r g i…

利用AI增强现实开发:基于CoreML的深度学习图像场景识别实战教程

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

指针求函数的最大值,传递的只有一个参数如何比较两个整数的最大值

指针求函数的最大值&#xff0c;传递的只有一个参数如何比较两个整数的最大值 指针求函数的最大值&#xff0c;传递的只有一个参数如何比较两个整数的最大值 文章目录 指针求函数的最大值&#xff0c;传递的只有一个参数如何比较两个整数的最大值指针求函数的最大值&#xff0…

【硬件模块】SHT20温湿度传感器

SHT20是一个用IIC通信的温湿度传感器。我们知道这个就可以了。 它支持的电压范围是2.1~3.6V&#xff0c;推荐是3V&#xff0c;所以如果我们的MCU是5V的&#xff0c;那么就得转个电压才能用了。 IIC常见的速率有100k&#xff0c;400k&#xff0c;而SHT20是支持400k的&#xff08…

yolo-word复现

github下载代码&#xff1a;https://github.com/AILab-CVC/YOLO-World 配置环境&#xff1a; 官方的方式 当然也可以按照官方给的配置方式去安装库&#xff0c;我也试了&#xff0c;出现小问题了。 我这边是从我本身的yolov8的环境克隆过来的&#xff0c;然后安装我环境里没有…