首页 > 编程 > Java > 正文

Java集合系列(9)--HashSet

2019-11-08 02:33:36
字体:
来源:转载
供稿:网友

前面我们已学习了ArrayList、LinkedList、HashMap、HashTable、TreeMap,接下来我们来学习HashSet。 首先我们对HashSet有一个整体的认识,然后学习它的源码,最后通过代码示例学会使用它。

一、HashSet基本概述

HashSet是由HashMap实现的,所以底层也是散列表(数组+链表)。 HashMap是无序的,且不允许元素重复,但HashSet允许元素为空。 HashSet是非同步的。如果多个线程同时访问一个HashSet,若其中至少一个线程修改了该set,那么就必须保持外部同步。这通常是通过封装该set的对象执行同步操作来完成的。 如果不存在这样的对象,则应该使用Collections.synchronizedSet(同步set)方法来包装set。在创建时完成该操作:

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

HashSet通过Iterator()返回的迭代器也是Fail-Fast机制。 易考点:

关注点 结论
结合底层实现的数据结构 由HashMap实现,散列表(数组+列表)
集合中元素是否允许为空 Key和value都可以为空
是否允许数据重复 不允许元素重复
是否有序 无序,是指不是按put进来的顺序
是否线程安全 非线程安全(不是同步的)

二、HashSet的数据结构

1>HashSet与Map关系如下图: image 从中可以得到: a.HashSet继承于AbstractSet,并且实现了Set接口; b、HashSet不允许元素重复,底层是由HashMap实现的。HashSet中哈有一个HashMap类型的成员变量map,HashSet的操作函数,都是基于map实现的。 2>HashSet的构造函数 1、默认构造函数

// 默认构造函数 public HashSet() { // 调用HashMap的默认构造函数,创建map map = new HashMap<E,Object>(); }2、带集合的构造函数// 带集合的构造函数 public HashSet(Collection<? extends E> c) { // 创建map。 // 为什么要调用Math.max((int) (c.size()/.75f) + 1, 16),从 (c.size()/.75f) + 1 和 16 中选择一个比较大的树呢? // 首先,说明(c.size()/.75f) + 1 // 因为从HashMap的效率(时间成本和空间成本)考虑,HashMap的加载因子是0.75。 // 当HashMap的“阈值”(阈值=HashMap总的大小*加载因子) < “HashMap实际大小”时, // 就需要将HashMap的容量翻倍。 // 所以,(c.size()/.75f) + 1 计算出来的正好是总的空间大小。 // 接下来,说明为什么是 16 。 // HashMap的总的大小,必须是2的指数倍。若创建HashMap时,指定的大小不是2的指数倍; // HashMap的构造函数中也会重新计算,找出比“指定大小”大的最小的2的指数倍的数。 // 所以,这里指定为16是从性能考虑。避免重复计算。 map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16)); // 将集合(c)中的全部元素添加到HashSet中 addAll(c); }3、指定HashSet初始容量和加载因子的构造函数 public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<E,Object>(initialCapacity, loadFactor); }4、指定HashSet初始容量的构造函数public HashSet(int initialCapacity) { map = new HashMap<E,Object>(initialCapacity); }5、指定HashSet初始容量和加载因子的构造函数HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor); }

三、HashSet遍历方式

1、通过Iterator遍历HashSet HashSet set = new HashSet(); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.PRintln(iterator); }2、通过for-each增强for循环遍历HashSetHashSet set = new HashSet();String[] arr = (String[])set.toArray(new String[0]);for (String str:arr) System.out.printf("for each : %s/n", str);

四、HashSet代码示例

package Test;import java.util.HashSet;import java.util.Iterator;/** * Created by LKL on 2017/2/19. * HashSet常用API的使用。 */public class TestHashSet1 { public static void main(String[] args) { // HashSet常用API testHashSetAPIs() ; } /* * HashSet除了iterator()和add()之外的其它常用API */ private static void testHashSetAPIs() { // 新建HashSet HashSet set = new HashSet(); // 将元素添加到Set中 set.add("a"); set.add("b"); set.add("c"); set.add("d"); set.add("e"); // 打印HashSet的实际大小 System.out.printf("size : %d/n", set.size()); // 判断HashSet是否包含某个值 System.out.printf("HashSet contains a :%s/n", set.contains("a")); System.out.printf("HashSet contains g :%s/n", set.contains("g")); // 删除HashSet中的“e” set.remove("e"); // 将Set转换为数组 String[] arr = (String[])set.toArray(new String[0]); for (String str:arr) System.out.printf("for each : %s/n", str); // 新建一个包含b、c、f的HashSet HashSet otherset = new HashSet(); otherset.add("b"); otherset.add("c"); otherset.add("f"); // 克隆一个removeset,内容和set一模一样 HashSet removeset = (HashSet)set.clone(); // 删除“removeset中,属于otherSet的元素” removeset.removeAll(otherset); // 打印removeset System.out.printf("removeset : %s/n", removeset); // 克隆一个retainset,内容和set一模一样 HashSet retainset = (HashSet)set.clone(); // 保留“retainset中,属于otherSet的元素” retainset.retainAll(otherset); // 打印retainset System.out.printf("retainset : %s/n", retainset); // 遍历HashSet for(Iterator iterator = set.iterator(); iterator.hasNext(); ) System.out.printf("iterator : %s/n", iterator.next()); // 清空HashSet set.clear(); // 输出HashSet是否为空 System.out.printf("%s/n", set.isEmpty()?"set is empty":"set is not empty"); }}

运行结果如下:

size : 5HashSet contains a :trueHashSet contains g :falsefor each : afor each : bfor each : cfor each : dremoveset : [a, d]retainset : [b, c]iterator : aiterator : biterator : citerator : dset is empty

文章只是作为自己的学习笔记,借鉴了网上的许多案例,如果觉得阔以的话,希望多交流,在此 谢过…


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表