HashSet的定义

HashSet类实现了Set接口,由一个实际上是HashMap实例的散列表​支持。不能保证该集合的迭代次序,这意味着该类不能保证元素随时间的不变顺序。这个类允许null元素。该类还为基本操作(如添加,删除,包含和大小)提供了恒定的时间性能,假定散列函数将元素正确地分散到桶中,我们将在文章中进一步讨论。
HashSet的一些重要特性是:

  • 实现Set Interface。
  • HashSet的基础数据结构是散列表。
  • 由于它实现了Set Interface,所以不允许重复值。
  • 您在HashSet中插入的对象不保证以相同顺序插入。对象基于其哈希码插入。
  • HashSet中允许使用NULL元素。
  • HashSet还实现了Searlizable和Cloneable接口。

现在为了维持恒定的时间性能,迭代HashSet需要的时间与HashSet实例的大小(元素数量)加上支持HashMap实例的“容量”(桶的数量)的总和成正比。因此,如果迭代性能很重要,不要将初始容量设置得太高(或者负载因子太低)是非常重要的。

初始容量:初始容量意味着在创建散列表(HashSet内部使用散列表数据结构)时创建桶的数量。如果当前尺寸变满,桶的数量将自动增加。负载因数:负载因数是衡量HashSet在其容量自动增加之前能够获得的满量程。当哈希表中的条目数量超过负载因子和当前容量的乘积时,散列表就会被重新映射(即重建内部数据结构),以便散列表大约是存储桶数量的两倍。

                  表格中存储的元素数量   加载因子= -----------------------------------------                        散列表的大小 

示例:如果内部容量为16并且加载因子为0.75,那么当表中有12个元素时,桶的数量会自动增加。

对性能的影响:
负载因子和初始容量是影响HashSet操作性能的两个主要因素。0.75的负载因子在时间和空间复杂度方面提供了非常有效的性能。如果我们将负载因子值增加得超过这个值,那么内存开销将会减少(因为它会减少内部重建操作),但是它会影响哈希表中的添加和搜索操作。为了减少重新哈希操作,我们应该明智地选择初始容量。如果初始容量大于最大入口数量除以负载因子,则不会发生重新刷新操作。

注:HashSet中的实现不同步,因为如果多个线程同时访问散列集,并且至少有一个线程修改了该集,它必须在外部同步。这通常是通过在自然封装集合的某个对象上进行同步来完成的。如果不存在这样的对象,则应该使用Collections.synchronizedSet方法来“包装”该集合。这最好在创建时完成,以防止意外的不同步访问集合,如下所示:

Set s = Collections.synchronizedSet(new HashSet(...));

HashSet中的构造函数:

  1. HashSet h = new HashSet();
    默认初始容量为16,默认加载因子为0.75。
  2. HashSet h = new HashSet(int initialCapacity);
    默认的0.75的loadFactor
  3. HashSet h = new HashSet(int initialCapacity,float loadFactor);
  4. HashSet h = new HashSet(Collection C);

下面的程序说明了HashSet的几个基本操作:

// Java program to demonstrate working of HashSet

import java.util.*;

class Test

{

public static void main(String[]args)

{

HashSet h = new HashSet();

// Adding elements into HashSet usind add()

h.add("India");

h.add("Australia");

h.add("South Africa");

h.add("India");// adding duplicate elements

// Displaying the HashSet

System.out.println(h);

System.out.println("List contains India or not:" +

h.contains("India"));

// Removing items from HashSet using remove()

h.remove("Australia");

System.out.println("List after removing Australia:"+h);

// Iterating over hash set items

System.out.println("Iterating over list:");

Iterator i = h.iterator();

while (i.hasNext())

System.out.println(i.next());

}

}

输出:

[South Africa, Australia, India]List contains India or not:trueList after removing Australia:[South Africa, India]Iterating over list:South AfricaIndia

HashSet的内部工作
由Map内部备份的所有Set接口类。HashSet使用HashMap在内部存储它的对象。您一定想知道,要在HashMap中输入值,我们需要一个键值对,但在HashSet中,我们只传递一个值。

存储在HashMap中
实际上,我们在HashSet中插入的值作为映射对象的关键字,并且其值java使用常量变量。所以在键值对中,所有键都具有相同的值。

在java文档中实现HashSet

private transient HashMap map;//构造函数 -  1//所有的构造函数都在内部创建HashMap对象。public HashSet(){    //创建内部支持HashMap对象    map = new HashMap();}//构造函数 -  2public HashSet(int initialCapacity){    //创建内部支持HashMap对象    map = new HashMap(initialCapacity);}//与map中的对象关联的虚拟值private static final Object PRESENT = new Object();

如果我们看一下HashSet类的add()方法:

public boolean add(E e){   return map.put(e,PRESENT)== null;}

我们可以注意到,HashSet类的add()方法通过传递指定的元素作为键和常量“PRESENT”作为其值,来内部调用支持HashMap对象的put()方法。

remove()方法也以相同的方式工作。它内部调用Map接口的remove方法。

public boolean remove(Object o){  return map.remove(o)== PRESENT;}

HashSet操作的时间复杂度:HashSet的基础数据结构是散列表。因此,对于添加,移除和查找(包含方法)操作,HashSet需要O(1)次的时间复杂度(平均或通常情况下)的时间复杂度。

HashSet中的方法:

  1. boolean add(E e):用于添加指定元素(如果不存在),如果存在则返回false。
  2. void clear():用于删除set中的所有元素。
  3. boolean contains(Object o): 如果元素存在于set中,则返回true。
  4. boolean remove(Object o):用于删除元素,如果它存在于set中。
  5. Iterator iterator(): 用于返回集合中元素的迭代器。
  6. boolean isEmpty():用于检查集合是否为空。返回true表示空,false表示非空条件。
  7. int size():用于返回集合的大小。
  8. Object clone():用于创建集合的浅表副本。

--------------------------------------------------------

转载自:https://www.breakyizhan.com/java/4658.html

hashset java 键值对_Java集合 - HashSet的定义以及用法相关推荐

  1. hashset java 键值对_Java中的各个容器的性能对比

    java中个个容器的属性,性能,参数对比: Java容器的性能及属性的对比 List:Vector,ArrayList,LinkedList Vector:内部是数组数据结构,可以理解为加锁的Arra ...

  2. 给定key值,在Binary Search Tree中查找最接近该键值的结点集合

    http://blog.csdn.net/zhouhao011280s/article/details/8044056 给定key值,在Binary Search Tree中查找最接近该键值的结点集合 ...

  3. SortedDictionaryTKey, TValue 类 表示根据键进行排序的键/值对的集合。

    SortedDictionary<TKey, TValue> 类   表示根据键进行排序的键/值对的集合. SortedDictionary<TKey, TValue> 中的每 ...

  4. java中的键值对_java中单个键值对的表示方式

    很多时候,我们只需保存单个键值对,并且希望很方便的取key值和value值. 虽然Map是专门用于存放键值对的,但是Map取key值和取value值不太方便,需要先获得keySet,然后遍历此keyS ...

  5. java地图源码_Java集合源码分析(四)HashMap

    一.HashMap简介 1.1.HashMap概述 HashMap是基于哈希表的Map接口实现的,它存储的是内容是键值对映射.此类不保证映射的顺序,假定哈希函数将元素适当的分布在各桶之间,可为基本操作 ...

  6. java map 红黑树_Java集合-TreeMap和红黑树

    TreeMap是一种通过实现了红黑树数据结构的Map集合. [图片有英文注释的均摘抄于国外文章] 首先,先来看一些基础概念. 1. 二叉排序树 二叉排序树的定义和性质: (1)若左子树不空,则左子树上 ...

  7. [Andriod官方训练教程]保存数据之保存键-值对的集合

    原文地址:https://developer.android.com/training/basics/data-storage/shared-preferences.html ------------ ...

  8. Java入门第111课——集合addAll、containsAll的用法

    问题 测试Collection接口中addAll方法.containsAll方法的用法,详细要求如下: 1)使用ArrayList构建集合c1,将字符串"java"."c ...

  9. java 定义抽象变量_Java抽象类和抽象方法定义与用法实例详解

    本文实例讲述了Java抽象类和抽象方法定义与用法.分享给大家供大家参考,具体如下: 一.Java抽象类 1.抽象类的说明 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都 ...

最新文章

  1. 【linux】多线程编程(c语言编程)
  2. 详细解析Java中抽象类和接口的区别
  3. 教育场景下的实时音频解决方案
  4. [jQuery] jQuery的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?
  5. Java并发编程——线程带来的风险
  6. 力扣441.排列硬币
  7. 2008,人力资源软件是否还依然
  8. Stack Overflow 2017 开发者调查报告(程序员必看)
  9. java-线程-使用阻塞队列(BlockingQueue)控制线程通信
  10. 在Visual Studio中使用Visual Basic教程:创建一个控制台应用
  11. mathtype——小白安装
  12. 使用3CDaemon 进行ftp 传输文件 (linux-开发板) 的方法
  13. 3个动作精准引流方法,放大操作,每天吸粉200+
  14. 解决VMware中的Windows Server 2012 R2无法成功安装Hyper-V的问题
  15. 为什么Wannacry 勒索病毒加密的部分数据能恢复?
  16. 教你把多个视频合并成一个视频的方法
  17. SSD系列算法原理讲解----(1)SSD系列算法介绍(主干网络、多尺度Feature Map预测)(笔记)
  18. Apollo星火计划学习笔记——Control 专项讲解(LQR)
  19. antd-mobile下拉加载
  20. 雨量水位监测站 水情监测

热门文章

  1. 漫画:如何证明sleep不释放锁,而wait释放锁?
  2. Properties文件位置
  3. 不创建 sequence 自增字段
  4. ContextMenu长按事件
  5. idea连接sqlserver及数据库操作
  6. 安卓逆向代码反混淆 Simplify工具 JEB2反混淆神器
  7. latex目录标题中间空一个字符
  8. gojs 节点右键点击事件_SWMM快速建模方法(3)—建立管线上下游节点编号
  9. linux docker安装_Linux上安装docker的完美教程
  10. java 字符串是否包含字符串_在Java中,如何检查字符串是否包含子字符串(忽略大小写)?...