当前位置: 首页 > 编程日记 > 正文

3.Java集合-HashSet实现原理及源码分析

一、HashSet概述:

HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持,它不保证set的迭代顺序很久不变。此类允许使用null元素

二、HashSet的实现:

对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,这也是为什么HashSet里面存储的元素是无序且不可重复的(因为HashMap里面的key是唯一的)

三、Hash源码如下:

  1 public class HashSet<E>  
  2    extends AbstractSet<E>  
  3    implements Set<E>, Cloneable, java.io.Serializable  
  4 4{  
  5    static final long serialVersionUID = -5024744406713321676L;  
  6  
  7    // 底层使用HashMap来保存HashSet中所有元素。  
  8    private transient HashMap<E,Object> map;  
  9      
 10    // 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。  
 11    private static final Object PRESENT = new Object();  
 12  
 13    /** 
 14     * 默认的无参构造器,构造一个空的HashSet。 
 15     *  
 16     * 实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。 
 17     */  
 18    public HashSet() {  
 19    map = new HashMap<E,Object>();  
 20    }  
 21  
 22    /** 
 23     * 构造一个包含指定collection中的元素的新set。 
 24     * 
 25     * 实际底层使用默认的加载因子0.75和足以包含指定 
 26     * collection中所有元素的初始容量来创建一个HashMap。 
 27     * @param c 其中的元素将存放在此set中的collection。 
 28     */  
 29    public HashSet(Collection<? extends E> c) {  
 30    map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));  
 31    addAll(c);  
 32    }  
 33  
 34    /** 
 35     * 以指定的initialCapacity和loadFactor构造一个空的HashSet。 
 36     * 
 37     * 实际底层以相应的参数构造一个空的HashMap。 
 38     * @param initialCapacity 初始容量。 
 39     * @param loadFactor 加载因子。 
 40     */  
 41    public HashSet(int initialCapacity, float loadFactor) {  
 42    map = new HashMap<E,Object>(initialCapacity, loadFactor);  
 43    }  
 44  
 45    /** 
 46     * 以指定的initialCapacity构造一个空的HashSet。 
 47     * 
 48     * 实际底层以相应的参数及加载因子loadFactor为0.75构造一个空的HashMap。 
 49     * @param initialCapacity 初始容量。 
 50     */  
 51    public HashSet(int initialCapacity) {  
 52    map = new HashMap<E,Object>(initialCapacity);  
 53    }  
 54  
 55    /** 
 56     * 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。 
 57     * 此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。 
 58     * 
 59     * 实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。 
 60     * @param initialCapacity 初始容量。 
 61     * @param loadFactor 加载因子。 
 62     * @param dummy 标记。 
 63     */  
 64    HashSet(int initialCapacity, float loadFactor, boolean dummy) {  
 65    map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);  
 66    }  
 67  
 68    /** 
 69     * 返回对此set中元素进行迭代的迭代器。返回元素的顺序并不是特定的。 
 70     *  
 71     * 底层实际调用底层HashMap的keySet来返回所有的key。 
 72     * 可见HashSet中的元素,只是存放在了底层HashMap的key上, 
 73     * value使用一个static final的Object对象标识。 
 74     * @return 对此set中元素进行迭代的Iterator。 
 75     */  
 76    public Iterator<E> iterator() {  
 77    return map.keySet().iterator();  
 78    }  
 79  
 80    /** 
 81     * 返回此set中的元素的数量(set的容量)。 
 82     * 
 83     * 底层实际调用HashMap的size()方法返回Entry的数量,就得到该Set中元素的个数。 
 84     * @return 此set中的元素的数量(set的容量)。 
 85     */  
 86    public int size() {  
 87    return map.size();  
 88    }  
 89  
 90    /** 
 91     * 如果此set不包含任何元素,则返回true。 
 92     * 
 93     * 底层实际调用HashMap的isEmpty()判断该HashSet是否为空。 
 94     * @return 如果此set不包含任何元素,则返回true。 
 95     */  
 96    public boolean isEmpty() {  
 97    return map.isEmpty();  
 98    }  
 99  
100    /** 
101     * 如果此set包含指定元素,则返回true。 
102     * 更确切地讲,当且仅当此set包含一个满足(o==null ? e==null : o.equals(e)) 
103     * 的e元素时,返回true。 
104     * 
105     * 底层实际调用HashMap的containsKey判断是否包含指定key。 
106     * @param o 在此set中的存在已得到测试的元素。 
107     * @return 如果此set包含指定元素,则返回true。 
108     */  
109    public boolean contains(Object o) {  
110    return map.containsKey(o);  
111    }  
112  
113    /** 
114     * 如果此set中尚未包含指定元素,则添加指定元素。 
115     * 更确切地讲,如果此 set 没有包含满足(e==null ? e2==null : e.equals(e2)) 
116     * 的元素e2,则向此set 添加指定的元素e。 
117     * 如果此set已包含该元素,则该调用不更改set并返回false。 
118     * 
119     * 底层实际将将该元素作为key放入HashMap。 
120     * 由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key 
121     * 与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true), 
122     * 新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变, 
123     * 因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中, 
124     * 原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。 
125     * @param e 将添加到此set中的元素。 
126     * @return 如果此set尚未包含指定元素,则返回true。 
127     */  
128    public boolean add(E e) {  
129    return map.put(e, PRESENT)==null;  
130    }  
131  
132    /** 
133     * 如果指定元素存在于此set中,则将其移除。 
134     * 更确切地讲,如果此set包含一个满足(o==null ? e==null : o.equals(e))的元素e, 
135     * 则将其移除。如果此set已包含该元素,则返回true 
136     * (或者:如果此set因调用而发生更改,则返回true)。(一旦调用返回,则此set不再包含该元素)。 
137     * 
138     * 底层实际调用HashMap的remove方法删除指定Entry。 
139     * @param o 如果存在于此set中则需要将其移除的对象。 
140     * @return 如果set包含指定元素,则返回true。 
141     */  
142    public boolean remove(Object o) {  
143    return map.remove(o)==PRESENT;  
144    }  
145  
146    /** 
147     * 从此set中移除所有元素。此调用返回后,该set将为空。 
148     * 
149     * 底层实际调用HashMap的clear方法清空Entry中所有元素。 
150     */  
151    public void clear() {  
152    map.clear();  
153    }  
154  
155    /** 
156     * 返回此HashSet实例的浅表副本:并没有复制这些元素本身。 
157     * 
158     * 底层实际调用HashMap的clone()方法,获取HashMap的浅表副本,并设置到  HashSet中。 
159     */  
160    public Object clone() {  
161        try {  
162            HashSet<E> newSet = (HashSet<E>) super.clone();  
163            newSet.map = (HashMap<E, Object>) map.clone();  
164            return newSet;  
165        } catch (CloneNotSupportedException e) {  
166            throw new InternalError();  
167        }  
168    }  
169 }

总结:

HashSet基于HashMap,这个HashMap中 key 就是用来存放 HashSet中的数据,HashMap中的value 填入的是一个常量值,所有Entry的value 都是这个值。

这也是HashSet 中存储的值是唯一且不可重复的原因

参考博文:http://www.cnblogs.com/ITtangtang/p/3948538.html

转载于:https://www.cnblogs.com/xuzekun/p/7461629.html

相关文章:

一个函数返回多个值

有两种方法&#xff1a;1.使用指针变量声明函数&#xff08;或者使用数组变量&#xff09;2.使用传出参数 第一种方法&#xff1a;函数返回的是一个指针地址&#xff08;数组地址&#xff09;&#xff0c;这个内存地址有多个变量寄存在里面。这个方法我不太会用&#xff0c;传…

4月30日或为上半年“最难打车日”

滴滴出行昨日发布预测&#xff0c;称由于周五通勤晚高峰及假期启程高峰叠加&#xff0c;4月30日下午或将成为今年上半年“最难打车日”&#xff0c;用户将遇到叫车排队甚至打不到车的情况。滴滴呼吁&#xff0c;请提前规划行程&#xff0c;预留充足时间&#xff0c;大家五一快乐…

exchange 2003配置ASSP 反垃圾邮件

Exchange上第三方反垃圾邮件用得比较多的是ORF&#xff0c;它直接运行在虚拟SMTP服务上&#xff0c;配置非常的方便。ASSP&#xff08;https://sourceforge.net/projects/assp/&#xff09; 是一个开源的反垃圾邮件代理&#xff0c;反垃圾效果也非常好&#xff0c;这里不讲如何…

中国人工智能学会通讯——人工智能在各医学亚专科的发展现状及趋势 1.3 人工智能在各医学亚专科的发展态势...

1.3 人工智能在各医学亚专科的发展态势 1. 人工智能在眼科领域的应用 2016年11月&#xff0c;Google的研究者Gulshan博士等人在美国医学协会杂志“Journal of the American Medical Association”上发表的一篇文章&#xff0c;运用deep learning算法&#xff08;卷积神经网络&a…

在ASP.NET中如何用C#.NET实现基于表单的验证

这篇文章引用到了Microsoft .NET类库中的以下名空间&#xff1a; System.Data.SqlClient System.Web.Security &#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff…

PHP学习笔记 第八讲 Mysql.简介和创建新的数据库

八、Mysql.简介和创建新的数据库1、mysql简介与概要mysql是一个小型关系型数据管理系统&#xff0c;开发者为瑞典mysqlab公司现在已经被sun公司收购1.可以处理拥有上千万条记录的大型数据2.支持常见SQL语句规范3.可移植高&#xff0c;安装简单小巧4.良好的运行效率&#xff0c;…

摆脱 FM!这些推荐系统模型真香

‍‍作者 | 梁唐来源 | TechFlow之前我们介绍了推荐当中应用得非常广泛的FM大家族&#xff0c;从FM这个模型衍生出了一系列的模型&#xff0c;从纯FM&#xff0c;到AFM、FFM、DeepFM等等一系列的FM模型&#xff0c;最后的终极版本是xDeepFM。这个模型非常复杂&#xff0c;可以说…

新技术、新思维开创公共安全管理新模式

智慧城市的建设在国内外许多地区正如火如荼的进行中&#xff0c;在为期六天的第十七届中国国际高新技术成果交易会&#xff08;高交会&#xff09;上&#xff0c;智慧城市这一话题再次引发观众及城市建设者们的热议。 尤其是高交会期间召开的“2015亚太智慧城市发展高峰论坛”&…

.Net 中字符串性能

Introduction 你在代码中处理字符串的方法可能会对性能产生令人吃惊的影响。在本文中&#xff0c;我需要考虑两个由于使用字符串而产生的问题&#xff1a;临时字符串变量的使用和字符串连接。 Background 每个项目都有需要你为其考虑编码标准的时候。使用 FxCop 是一个好的开…

Lambda表达式可以被转换为委托类型

void Main() { //向Users类中增加两人; List<Users> usernew List<Users>{ new Users{ID1,Name"Jalen",Age23}, new Users{ID12,Name"Administrator",Age32}, }; //接下来就是利用Linq提供的新的方法来进行相关操作; var userslistuser.Wher…

人工干预如何提高模型性能?看这文就够了!

作者 | Preetam Joshi译者 | 吴家帆出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;有一些行业对误报非常敏感&#xff0c;如金融行业&#xff0c;在对信用卡欺诈检测时&#xff0c;如果检测系统将用户的行为错误地分类为欺诈&#xff0c;这将对该金融机构的声誉产生…

一种无需留坑为页面动态添加View方案

在Activity或Fragment页面动态添加View&#xff0c;有其应用场景&#xff0c;比如配合运营在首页动态插入H5活动页&#xff08;如下图手淘的雪花例示[1]&#xff09;,在页面头部插入通知View等。本文结合ActivityLifecycleCallbacks[2]及DecorView使用&#xff0c;为类似需求提…

边缘加速创新和AI应用,Xilinx推出Kria自适应系统模块产品组合

为了帮助开发者更容易使用FPGA和SoC的功能&#xff0c;赛灵思在开发工具上做了不少的投入&#xff0c;自适应系统模块&#xff08;SOM&#xff09;产品组合就是其中之一。 近日&#xff0c;赛灵思宣布推出Kria™自适应系统模块&#xff08; SOM &#xff09;产品组合&#xff…

windows计算器

using System; using System.Drawing; using System.Windows; using System.Windows.Forms; using System.Collections; using System.ComponentModel; using System.Data; namespace comput{ /// <summary> /// 这是一个计算器的简单实现。 /// </summary&…

哈夫曼树的构造

[转载于网易博客&#xff0c;具体地址不详] 构造哈夫曼树的过程是这样的 一、构成初始集合 对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F{T1,T2,T3,...,Ti,...,Tn}&#xff0c;其中每棵二叉树Ti中只有一个权值为Wi的根结点&#xff0c;它的左右子树均为空…

物联网时代全面降临

从智能建筑到零售&#xff0c;英特尔物联网解决方案可以说是华丽丽地惊艳着大家的大脑和眼球&#xff0c;一切的不可能似乎都在朝着可能的方向努力着。在2015 MWC上&#xff0c;英特尔再次用各种神奇的物联网设备告诉大家&#xff1a;物联网时代已经来临。 “半边天”的力量&am…

Linux C++/Java/Web/OC Socket网络编程

一&#xff0c;Linux C Socket网络编程 1.什么是TCP/IP、UDP&#xff1f; TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;即传输控制协议/网间协议&#xff0c;是一个工业标准的协议集&#xff0c;它是为广域网&#xff08;WANs&#xff09;设…

ASP.NET抓取其他网页代码

在.Net 平台下&#xff0c;创建一个ASP.Net的程序 1、引用两个NAMESPACE using System.Text //因为用了Encoding类 using System.Net //因为用了WebClient 类 2、整个程序用了三个控件 txtUrl //输入你要获取的网页地址 TEXTBOX控件 txtBody //得到你要获取的网…

特斯拉遇上 CPU:程序员的心思你别猜

作者 | 码农的荒岛求生来源 | 码农的荒岛求生图源 | 视觉中国18世纪流水线的诞生带来了制造技术的变革&#xff0c;人类当今拥有琳琅满目物美价廉的商品和流水线技术的发明密不可分&#xff0c;因此当你喝着可乐、吹着空调、坐在特斯拉里拿着智能手机刷这篇文章时需要感谢流水线…

《算法技术手册》一2.4.6 二次方的算法性能

2.4.6 二次方的算法性能 现在考虑一个类似的问题&#xff1a;两个n位的整数相乘。例2-4展示了使用小学课堂上学过的算法实现的乘法运算&#xff0c;其中n位数字的表示方法与之前的加法一样。 例2-4&#xff1a;mult乘法的Java实现 public static void mult (int[] n1, int[] n2…

如何使用 OpenCV 实现图像均衡?

来源 | 小白视觉志头图 | 下载于视觉中国我们已经练习了很多图像处理——操作图像&#xff08;精确地说是图像矩阵&#xff09;。为此&#xff0c;我们探索了图像的均衡方法&#xff0c;以便在一定程度上增强对比度&#xff0c;以使被处理的图像看起来比原始图像更好&#xff0…

《中国人工智能学会通讯》——1.42 理解情感

1.42 理解情感 安德鲁摩尔认为&#xff0c;人工智能能“感受”人类情感是人工智能研究领域最重要、也最先进的一个方向。扬波利斯基认为&#xff0c;计算机能够理解语言的能力最终会向人和计算机“无缝沟通”的方向发展。 越来越精准的图像、声音和面部识别系统能让计算机更好探…

matlab中help所有函数功能的英文翻译

doc funname 在帮助浏览器中打开帮助文档help funname 在命令窗口打开帮助文档helpbrowser 直接打开帮助浏览器lookfor funname 搜索某个关键字相关函数demo 打开视频教程 转http://blog.renren.com/share/239121107/690877048 里面有些不全的&#xff0c;自己用到的已添加…

C# 静态构造函数

&#xff08;1&#xff09;用于对静态字段、只读字段等的初始化。 &#xff08;2&#xff09;添加static关键字&#xff0c;不能添加访问修饰符&#xff0c;因为静态构造函数都是私有的。 &#xff08;3&#xff09;类的静态构造函数在给定应用程序域中…

破解数据流通痛点,华控清交的隐私计算之道

从无序中寻找踪迹&#xff0c;从眼前事探索未来。 正值 IT 黄金十年新开端&#xff0c; CSDN 欲以中立技术社区专业、客观的角度&#xff0c;深度探讨中国前沿 IT 技术演进&#xff0c;现在推出年度重磅企划栏目——「拟合」&#xff0c;通过对话企业高管大咖&#xff0c;跟踪报…

mac系统添加VSCode到右键菜单(转)

转自&#xff1a;https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001470969077294a6455fc9cd1f48b69f82cd05e7fa9b40000 在Mac系统上&#xff0c;Finder选中一个目录&#xff0c;右键菜单并没有“通过Code打开”这个操作。不过我们可以…

在 C# 中通过 P/Invoke 调用Win32 DLL

&#xff0c;.NET Framework 1.0 或 1.1 版类库中存在任何 Windows 所没有的功能限制都不足为怪。毕竟&#xff0c;32 位的 Windows&#xff08;不管何种版本&#xff09;是一个成熟的操作系统&#xff0c;为广大客户服务了十多年。相比之下&#xff0c;.NET Framework 却是一个…

xp/2003开关3389指令

开启3389&#xff1a; echo offtitle 开启3389clsrem 开启3389reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 00000000 /f >nulecho.echo 提示你&#xff1a;3389已经开启 关闭3389&…

TIOBE 新榜单:Python 超越 Java 重回第二,Rust 崛起

作者 | 苏宓出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;TIOBE 官方最新发布了 5 月的编程语言榜单&#xff0c;不妨一起来看一下本月榜单中又有哪些最新的变化呢&#xff1f;Python 重回第二和 4 月相比&#xff0c;本月榜单的 TOP 10 中变化最大的非 Python 与…

Docker编排工具Fig介绍

本文讲的是Docker编排工具Fig介绍&#xff0c;【编者的话】Fig是一个基于Docker的用于快速搭建开发环境的工具&#xff0c;目前Fig团队已经加入Docker公司。Fig通过一个配置文件来管理多个Docker容器&#xff0c;非常适合组合使用多个容器进行开发的场景。Fig可以和Docker一起来…