Java集合---HashSet的源码分析

一、  HashSet概述:

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

 

二、  HashSet的实现:

   对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成, 

HashSet的源代码如下:

 

1 public class HashSet<E>  
2    extends AbstractSet<E>  
3    implements Set<E>, Cloneable, java.io.Serializable  
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    }  
} 

 

三、 相关说明:

   对于HashSet中保存的对象,请注意正确重写其equals和hashCode方法,以保证放入的对象的唯一性。

 

转载于:https://www.cnblogs.com/ITtangtang/p/3948538.html

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

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

相关文章

lambda语法_Java Lambda语法替代

lambda语法关于lambda-dev邮件列表的讨论已经开始解决lambdas /函数文字的Java语言语法应该是什么样的问题。 让我们看一个稍微平凡的例子&#xff0c;然后尝试弄清楚问题。 Perl的人有一个很好的例子&#xff0c;说明以某种功能性的方式使用函数引用–他们称其为Schwartzian变…

CSDN论坛上的一道算法题

源地址为&#xff1a;http://bbs.csdn.net/topics/390854089 昨天晚上在CSDN论坛上看到这道题&#xff0c;思索一番后想到一个解决方案&#xff0c;也简单实现了。今天早上把博客补一补。算是做个笔记吧。 题目&#xff1a; 有m个人面向南方站成一排(m ≥1)&#xff0c;每喊一次…

Eclipse程序员要掌握的常用快捷键

判断一个人的编程水平&#xff0c;就看他用键盘多&#xff0c;还是鼠标多。用键盘一是为了输入代码&#xff08;当然了&#xff0c;也包括注释&#xff09;&#xff0c;再有就是熟练使用快捷键。曾有人在豆瓣评《卓有成效的程序员》&#xff1a;“人有多大懒&#xff0c;才有多…

spring依赖注入_Spring依赖注入技术的发展

spring依赖注入回顾Spring框架的历史&#xff0c;您会发现在每个发行版中实现依赖注入的方法越来越多。 如果您使用该框架已经超过一个月&#xff0c;那么在这篇回顾性文章中可能不会发现任何有趣的东西。 除了Scala中的最后一个示例&#xff0c;没有其他东西希望如此。 首先是…

java 获取oracle mysql sqlserver 链接 connection

import java.sql.Connection; import java.sql.DriverManager; //获取sqlserver connection public static Connection getSQLServerConn(){ Connection dbConn null; String driverName "com.microsoft.sqlserver.jdbc.SQLServerDriver"; …

TortoiseSVN菜单项功能说明

原帖地址&#xff1a;http://blog.csdn.net/windone0109/article/details/4030274 TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具。通过使用它&#xff0c;我们可以可视化的管理我们的版本库。不过由于它只是一个客户端&#xff0c;所以它不能对版本库进行权限管理。…

hornetq_Spring 3 HornetQ 2.1集成教程

hornetq通过Spring框架使用JBoss的新超高性能消息传递系统。 HornetQ是一个开放源代码项目&#xff0c;用于构建多协议&#xff0c;可嵌入&#xff0c;非常高性能的集群异步消息传递系统。 它是用Java编写的&#xff0c;并且可以在具有Java 5或更高版本运行时的任何平台上运行…

zoj 3811 untrusted patrol

昨天网赛的C题&#xff0c;我负责的&#xff0c;题意有些模模糊糊的 我首先弄清楚了题意&#xff0c;即要求一个patrol是否可能巡视过所有的点&#xff0c;首先整个图要是连通的&#xff0c;这个在建图的时候边用下并查集即可&#xff0c;然后某些点装了传感器&#xff0c;传感…

上周热点回顾(9.1-9.7)

热点随笔&#xff1a; 魅族的“火爆”预定表示“呵呵呵”-不要怪我拆穿&#xff08;tankaixiong&#xff09; 【调侃】IOC前世今生&#xff08;家住腊树下&#xff09; 跟着8张思维导图学习javascript&#xff08;Ico_Coco&#xff09; 下一代Asp.net开发规范OWIN&#xff08;…

mockito手动注入依赖_依赖注入–手动方式

mockito手动注入依赖依赖注入是一种将行为与依赖解决方案分开的技术。 用简单的话来说&#xff0c;它使开发人员可以定义具有特定功能的类&#xff0c;这些功能取决于各种协作者&#xff0c;而不必定义如何获取对这些协作者的引用。 以此方式&#xff0c;实现了各个组件之间的解…

ubuntu使用root权限登录的设置方法

Ubuntu系统默认是不允许用户以root身份登录的&#xff0c;在网上找到的方法如下&#xff1a; 1、首先设置root密码&#xff0c;利用现有管理员帐户登陆Ubuntu&#xff0c;在终端执行命令&#xff1a;sudo passwd root&#xff0c;接着输入密码和root密码&#xff0c;重复密码。…

visio 小技巧

Visio作图非常的方便 目前我还是用Visio2003&#xff0c;有一些小技巧&#xff0c;记录一下。 1、visio修改文本框文字对齐方式。默认的对齐方式是上下、左右居中。修改的位置: 在一个文档中可以插入多个标签页&#xff0c;当需要分页&#xff0c;用不同页归类不同信息的时候使…

java实现bean实体与map集合相互转换

方法一 //bean装换成map public static Map<?, ?> objectToMap2(Object obj) { if(obj null) return null; return new org.apache.commons.beanutils.BeanMap(obj); } 方法二 //bean装换成map public static Map&l…

java中字符串的精确匹配_Java最佳实践–字符串性能和精确字符串匹配

java中字符串的精确匹配在使用Java编程语言时&#xff0c;我们将继续讨论与建议的实践有关的系列文章&#xff0c;我们将讨论String性能调优。 我们将专注于如何有效地处理字符串创建&#xff0c; 字符串更改和字符串匹配操作。 此外&#xff0c;我们将提供我们自己的用于精确字…

My.Ioc 代码示例——避免循环依赖

本文的目的在于通过一些示例&#xff0c;向大家说明 My.Ioc 支持哪些类型的依赖关系。也就是说&#xff0c;如何设计对象不会导致循环依赖。 在 Ioc 世界中&#xff0c;循环依赖是一个顽敌。这不仅因为它会导致 Ioc 容器抛出异常&#xff0c;而且还因为它是不可预知的&#xff…

java实现base64加密解密

/** * 加密 * param str * return */ public static String getStr(String str){ BASE64Encoder base64 new BASE64Encoder(); return base64.encode(str.getBytes()); } /** * 解密 * param str * return * t…

设计模式之单件模式(Singleton Pattern)

一.单件模式是什么&#xff1f; 单件模式也被称为单例模式&#xff0c;它的作用说白了就是为了确保“该类的实例只有一个” 单件模式经常被用来管理资源敏感的对象&#xff0c;比如&#xff1a;数据库连接对象、注册表对象、线程池对象等等&#xff0c;这种对象如果同时存在多个…

asp.net中两款文本编辑器NicEdit和Kindeditor

分类&#xff1a; C#/ASP.Net 2012-10-09 22:35 665人阅读 评论(0) 收藏 举报 文本编辑asp.nettextboxserveraspsafari目录(?)[] 做过Web开发的朋友相信都使用过富文本编辑器&#xff0c;比较出名的CuteEditor和CKEditor很多人应该已经使用过&#xff0c;在功能强大的同时需要…

导出oracle awr分析报告,配置oracle内存参数,察看表空间使用率

cmd 命令生成awr报告: cmd 窗口 输入 -> Sqlplus sys/orclorcl as sysdba (sys登陆oracle).导出awr命令 ?/rdbms/admin/awrrpt.sql 3..输入导出的文件格式 为 html 回车 4输入数字1 为导出今天的分析报告 &#xff0c;2 3 。。。&#xff0c;回车 5.输入开始 snap id…

android多点触控自由对图片缩放

在系统的相册中,观看相片就可以用多个手指进行缩放.要实现这个功能,只需要这几步:1.新建项目,在项目中新建一个ZoomImage.javapublic class ZoomImageView extends View {//初始化状态常量public static final int STATUS_INIT1;//图片放大状态常量public static final int STA…