HashSet是一个没有重复元素的集合。接下来通过示例代码介绍java中hashset的知识。有兴趣的朋友来看看吧。
第1部分 HashSet介绍
HashSet 简介
HashSet是一个没有重复元素的集合。
它由HashMap实现,HashMap不保证元素的顺序,HashSet允许使用null元素。
HashSet是异步的。如果多个线程同时访问一个哈希集,并且其中至少有一个线程修改了该集,那么它必须保持外部同步。这通常是通过对自然封装集合的对象执行同步操作来完成的。如果不存在这样的对象,您应该使用Collections.synchronizedSet方法来“包装”该集合。最好在创建时这样做,以防止对该集合的意外异步访问:
set s=collections . synchronized set(new HashSet(.));
HashSet通过iterator()返回的迭代器是fail-fast。
HashSet的构造函数
//默认构造函数
公共哈希表()
//带有集合的构造函数
public HashSet(集合?扩展英中)
//指定HashSet的初始容量和加载因子的构造函数
公共哈希集(int initialCapacity,float loadFactor)
//指定哈希集初始容量的构造函数
公共哈希集(int initialCapacity)
//指定HashSet的初始容量和加载因子的构造函数。假人没有效果。
HashSet(int initialCapacity,float loadFactor,boolean dummy)
HashSet的主要API
布尔加法(E对象)
空清除()
对象克隆()
布尔包含(对象对象)
布尔型isEmpty()
迭代器迭代器()
布尔删除(对象对象)
int size()
第2部分 HashSet数据结构
HashSet的继承关系如下:
java.lang.Object
Java . util . abstract collection one
java.util.AbstractSetE
Java . util . hash set
公共类哈希特
扩展抽象集
实现SetE,Cloneable,java.io.Serializable { }
HashSet和Map之间的关系如下:
从图中可以看出:
(01) HashSet从AbstractSet继承,实现Set接口。
(02)hashset的本质是一个“没有重复元素”的集合,通过HashMap实现。HashSet包含一个HashMap类型的成员变量‘map’,HashSet的操作函数实际上是由map实现的。
第3部分 HashSet源码解析(基于JDK1.6.0_45)
为了更好的理解HashSet的原理,下面对HashSet的源代码进行分析。
包java.util
公共类哈希特
扩展抽象集
实现SetE、Cloneable、java.io.Serializable
{
static final long serial version uid=-5024744406713321676 l;
//HashSet通过map(HashMap对象)保存内容
私有瞬态HashMapE,对象映射;
//PRESENT是将key-value对应的值插入到映射中。
//因为HashSet中只需要key,而HashMap是键值键值对;
//所以,在添加键值对进行映射时,键值对的值固定为PRESENT。
私有静态最终对象PRESENT=new Object();
//默认构造函数
public HashSet() {
//调用HashMap的默认构造函数创建映射
map=new HashMapE,Object();
}
//带有集合的构造函数
public HashSet(集合?扩展E c) {
//创建地图。
//为什么要调用math.max ((int) (c.size()/.75f) 1,16)并从(c.size()/.75f) 1和16中选择更大的树?
//首先解释一下(c.size()/.75f) 1
//因为考虑到HashMap的效率(时间成本和空间成本),HashMap的加载因子是0.75。
//当HashMap的“threshold”(threshold=HashMap的总大小*加载因子)“HashMap的实际大小”时,
//你需要把HashMap的容量增加一倍。
//所以,用(c.size()/.75f) 1计算出来的正好是总的空间大小。
//接下来解释一下为什么是16。
hashmap的总大小必须是2的指数倍。如果创建HashMap时指定的大小不是2的指数倍数;
//也会在HashMap的构造函数中重新计算,找出大于“指定大小”的2的最小指数倍的个数。
//所以,这里指定16是出于性能考虑。避免重复计算。
map=new HashMapE,Object(math . max((int)(c . size()/. 75f)1,16));
//将集合(三)中的全部元素添加到哈希特中
addAll(c);
}
//指定哈希特初始容量和加载因子的构造函数
公共哈希集(int initialCapacity,float loadFactor) {
map=new HashMapE,Object(initialCapacity,load factor);
}
//指定哈希特初始容量的构造函数
公共哈希集(int initialCapacity) {
map=new HashMapE,Object(初始容量);
}
HashSet(int initialCapacity,float loadFactor,boolean dummy) {
map=new LinkedHashMapE,Object(initialCapacity,load factor);
}
//返回哈希特的迭代器
公共迭代器迭代器(){
//实际上返回的是散列表的"钥匙集合的迭代器"
返回map.keySet().迭代器();
}
public int size() {
返回地图。size();
}
public boolean isEmpty() {
返回地图。isempty();
}
公共布尔包含(对象o) {
返回地图。包含键(o);
}
//将元素(五)添加到哈希特中
公共布尔加法(E e) {
return map.put(e,PRESENT)==null;
}
//删除哈希特中的元素(o)
公共布尔移除(对象o) {
返回地图。remove(o)==PRESENT;
}
公共void clear() {
地图。clear();
}
//克隆一个哈希集,并返回目标对象
公共对象克隆(){
尝试{
哈希集合newSet=(哈希集合)super。clone();
newSet.map=(HashMapE,Object)map。clone();
返回新闻集
} catch(CloneNotSupportedException e){
抛出新的内部错误();
}
}
//java.io.Serializable的写入函数
//将哈希特的"总的容量,加载因子,实际容量,所有的元素"都写入到输出流中
私有void writeObject(Java。io。对象输出流
抛出java.io.IOException {
//写出任何隐藏的序列化魔术
s。defaultwriteobject();
//写出散列表容量和加载因子
s。写int(map。容量());
s。写浮点(映射。负载系数());
//写出大小
s。写int(map。size());
//按照正确的顺序写出所有元素。
对于(迭代器i=map.keySet().迭代器();I .有next();)
s。writeobject(I . next());
}
//java.io.Serializable的读取函数
//将哈希特的"总的容量,加载因子,实际容量,所有的元素"依次读出
私有void读取对象(Java。io。对象输入流
抛出java.io.IOException,ClassNotFoundException {
//读入任何隐藏的序列化魔术
s。默认读取对象();
//读入哈希表容量和加载因子,并创建后备哈希表
int capacity=s . readint();
浮点加载因子=s . read float();
map=(((HashSet)this)链接HashSet的instanceof?
新的LinkedHashMapE,Object(capacity,loadFactor):
new HashMapE,Object(capacity,load factor));
//读入大小
int size=s . readint();
//以正确的顺序读入所有元素。
for(int I=;isizei ) {
E E=(E)s . read object();
map.put(e,PRESENT);
}
}
}
说明:哈希集的代码实际上非常简单,通过上面的注释应该很能够看懂。它是通过散列表实现的,若对哈希特的理解有困难,建议先学习以下散列表学完散列表之后,在学习哈希特就非常容易了。
第4部分 HashSet遍历方式
4.1 通过Iterator遍历HashSet
第一步:根据迭代器()获取哈希特的迭代器。
第二步:遍历迭代器获取各个元素。
//假设设置是哈希特对象
for(Iterator迭代器=集合。迭代器();
迭代器。有next();) {
迭代器。next();
}
4.2 通过for-each遍历HashSet
第一步:根据托阵列()获取哈希特的元素集合对应的数组。
第二步:遍历数组,获取各个元素。
//假设设置是哈希特对象,并且设置中元素是线类型
String[]arr=(String[])集。to数组(新字符串[0]);
对于(字符串字符串:arr)
系统。出去。printf(' for each:% s \ n ',str);
哈希特的遍历测试程序如下:
导入Java。util。随机;
导入Java。util。迭代器;
导入Java。util。hashset
/*
* @desc介绍哈希特遍历方法
*
*
*/
公共类HashSetIteratorTest {
公共静态void main(String[] args) {
//新建哈希特
HashSet set=new HashSet();
//添加元素到哈希特中
for(int I=;我;我)
设置。add(“I”);
//通过迭代程序遍历哈希特
iteratorHashSet(集合);
//通过对于每个人遍历哈希特
foreachHashSet(集合);
}
/*
* 通过迭代程序遍历哈希集。推荐方式
*/
私有静态空的迭代器哈希集(哈希集){
for(Iterator迭代器=集合。迭代器();
迭代器。有next();) {
系统。出去。printf('迭代器:% s \ n ',迭代器。next());
}
}
/*
* 通过对于每个人遍历哈希集。不推荐!此方法需要先将一组转换为数组
*/
私有静态void foreachHashSet(HashSet集){
String[]arr=(String[])集。to数组(新字符串[]);
对于(字符串字符串:arr)
系统。出去。printf(' for each:% s \ n ',str);
}
}
运行结果:
迭代器:3
迭代器:2
迭代器:1
迭代器:0
迭代器:4
每个:3
每个:2
每个:1
对于每个:0
每个:4
第5部分 HashSet示例
下面我们通过实例学习如何使用哈希特
导入Java。util。迭代器;
导入Java。util。hashset
/*
* @ desc哈希特常用应用程序接口的使用。
*
* @作者天行
*/
公共类HashSetTest {
公共静态void main(String[] args) {
//哈希集常用应用程序接口
testHashSetAPIs();
}
/*
*哈希集除了迭代器()和添加()之外的其它常用应用程序接口
*/
私有静态void testHashSetAPIs() {
//新建哈希特
HashSet set=new HashSet();
//将元素添加到一组中
设置。添加(' a ');
设置。添加(' b ');
设置。add(' c ');
设置。add(' d ');
设置。添加(' e ');
//打印哈希特的实际大小
System.out.printf('size : %d\n ',set。size());
//判断哈希特是否包含某个值
系统。出去。printf(' HashSet包含一个:% s \ n ',Set。包含(' a ');
系统。出去。printf(' HashSet包含g:% s \ n ',Set。包含(' g ');
//删除哈希特中的" e "
设置。删除(' e ');
//将一组转换为数组
String[]arr=(String[])集。to数组(新字符串[]);
对于(字符串字符串:arr)
系统。出去。printf(' for each:% s \ n ',str);
//新建一个包含b、c、f的哈希特
HashSet other set=new HashSet();
另一套。添加(' b ');
另一套。add(' c ');
另一套。添加(' f ');
//克隆一个removeset,内容和设置一模一样
HashSet remove set=(HashSet)set。clone();
//删除"删除集中,属于其他集合的元素"
移除套件。全部删除(其他设置);
//打印移除集
系统。出去。printf('移除集合:% s \ n ',移除集合);
//克隆一个保留集,内容和设置一模一样
HashSet retain set=(HashSet)set。clone();
//保留"保留集中,属于其他集合的元素"
保留设置。保留全部(其他集);
//打印保留集
系统。出去。printf(' retainset:% s \ n ',retainset);
//遍历哈希特
for(Iterator迭代器=集合。迭代器();
迭代器。有next();)
系统。出去。printf('迭代器:% s \ n ',迭代器。next());
//清空哈希特
设置。clear();
//输出哈希特是否为空
System.out.printf('%s\n ',set.isEmpty()?“集为空”:“集不为空”);
}
}
运行结果:
尺寸:5
哈希特包含一个:正确
哈希特包含高:错
每个:d
每个:b
每个:c
每个:一个
移除集:[d,a]
保留集:[乙,丙]
迭代器:d
迭代器:b
迭代器:c
迭代器:a
集合为空
以上所述是小编给大家介绍的Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)中的哈希特详解和使用示例_动力节点Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)学院整理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。