java 集合系列目录:

Java 集合系列 01 总体框架

Java 集合系列 02 Collection架构

Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例

Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例

Java 集合系列 05 Vector详细介绍(源码解析)和使用示例

Java 集合系列 06 Stack详细介绍(源码解析)和使用示例

Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和性能分析)

Java 集合系列 08 Map架构

Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

Java 集合系列 11 hashmap 和 hashtable 的区别

Java 集合系列 12 TreeMap

Java 集合系列 13 WeakHashMap

Java 集合系列 14 hashCode

Java 集合系列 15 Map总结

Java 集合系列 16 HashSet

Java 集合系列 17 TreeSet

概述

第1 部分 HashSet介绍 

  1.1 HashSet 简介

  1.2 HashSet的构造函数

  1.3 HashSet的主要API

第2 部分 HashSet数据结构

第3 部分 源码分析

第1 部分 HashSet介绍

1.1 HashSet 简介

  HashSet 是一个没有重复元素的集合。它是由HashMap实现的,不保证元素的顺序,而且HashSet允许使用 null 元素

HashSet是非同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该 set 进行意外的不同步访问:

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

1.2 HashSet的构造函数

// 默认构造函数
public HashSet() // 带集合的构造函数
public HashSet(Collection<? extends E> c) // 指定HashSet初始容量和加载因子的构造函数
public HashSet(int initialCapacity, float loadFactor) // 指定HashSet初始容量的构造函数
public HashSet(int initialCapacity) // 指定HashSet初始容量和加载因子的构造函数,dummy没有任何作用
HashSet(int initialCapacity, float loadFactor, boolean dummy)

1.3 HashSet的主要API

 boolean add(E e) 如果此 set 中尚未包含指定元素,则添加指定元素。 void clear() 从此 set 中移除所有元素。 Object clone() 返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。 boolean contains(Object o) 如果此 set 包含指定元素,则返回 true。 boolean isEmpty() 如果此 set 不包含任何元素,则返回 true。 Iterator<E> iterator() 返回对此 set 中元素进行迭代的迭代器。 boolean remove(Object o) 如果指定元素存在于此 set 中,则将其移除。 int size() 返回此 set 中的元素的数量(set 的容量)。 

第2 部分 HashSet数据结构

HashSet的继承关系如下:

java.lang.Object↳     java.util.AbstractCollection<E>↳     java.util.AbstractSet<E>↳     java.util.HashSet<E>public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, java.io.Serializable { }

HashSet与Map关系如下图:

从图中可以看出:
(01) HashSet继承于AbstractSet,并且实现了Set接口。
(02) HashSet的本质是一个"没有重复元素"的集合,它是通过HashMap实现的。HashSet中含有一个"HashMap类型的成员变量"map,HashSet的操作函数,实际上都是通过map实现的。

第3 部分 源码分析

  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         // HashSet是通过map(HashMap对象)保存内容的
  8     private transient HashMap<E,Object> map;
  9
 10     // PRESENT是向map中插入key-value对应的value
 11     // 因为HashSet中只需要用到key,而HashMap是key-value键值对;
 12     // 所以,向map中添加键值对时,键值对的值固定是PRESENT
 13     private static final Object PRESENT = new Object();
 14
 15      // 默认构造函数
 16      //default initial capacity (16) and load factor (0.75)
 17     public HashSet() {
 18             // 调用HashMap的默认构造函数,创建map
 19         map = new HashMap<>();
 20     }
 21
 22     // 带集合的构造函数
 23     public HashSet(Collection<? extends E> c) {
 24             // 创建map。
 25         // 为什么要调用Math.max((int) (c.size()/.75f) + 1, 16),从 (c.size()/.75f) + 1 和 16 中选择一个比较大的树呢?
 26         // 首先,说明(c.size()/.75f) + 1
 27         //   因为从HashMap的效率(时间成本和空间成本)考虑,HashMap的加载因子是0.75。
 28         //   当HashMap的“阈值”(阈值=HashMap总的大小*加载因子) < “HashMap实际大小”时,
 29         //   就需要将HashMap的容量翻倍。
 30         //   所以,(c.size()/.75f) + 1 计算出来的正好是总的空间大小。
 31         // 接下来,说明为什么是 16 。
 32         //   HashMap的总的大小,必须是2的指数倍。若创建HashMap时,指定的大小不是2的指数倍;
 33         //   HashMap的构造函数中也会重新计算,找出比“指定大小”大的最小的2的指数倍的数。
 34         //   所以,这里指定为16是从性能考虑。避免重复计算。
 35         map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
 36         // 将集合(c)中的全部元素添加到HashSet中
 37         addAll(c);
 38     }
 39
 40     // 指定HashSet初始容量和加载因子的构造函数
 41     public HashSet(int initialCapacity, float loadFactor) {
 42         map = new HashMap<>(initialCapacity, loadFactor);
 43     }
 44
 45     // 指定HashSet初始容量的构造函数
 46     public HashSet(int initialCapacity) {
 47         map = new HashMap<>(initialCapacity);
 48     }
 49
 50     /**
 51      * Constructs a new, empty linked hash set.  (This package private
 52      * constructor is only used by LinkedHashSet.) The backing
 53      * HashMap instance is a LinkedHashMap with the specified initial
 54      * capacity and the specified load factor.
 55      *
 56      * @param      initialCapacity   the initial capacity of the hash map
 57      * @param      loadFactor        the load factor of the hash map
 58      * @param      dummy             ignored (distinguishes this
 59      *             constructor from other int, float constructor.)
 60      * @throws     IllegalArgumentException if the initial capacity is less
 61      *             than zero, or if the load factor is nonpositive
 62      */
 63      //以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。
 64      //dummy 为标识 该构造函数主要作用是对LinkedHashSet起到一个支持作用
 65     HashSet(int initialCapacity, float loadFactor, boolean dummy) {
 66         map = new LinkedHashMap<>(initialCapacity, loadFactor);
 67     }
 68
 69     // 返回HashSet的迭代器
 70     public Iterator<E> iterator() {
 71         return map.keySet().iterator();
 72     }
 73
 74     public int size() {
 75         return map.size();
 76     }
 77
 78     public boolean isEmpty() {
 79         return map.isEmpty();
 80     }
 81
 82     public boolean contains(Object o) {
 83         return map.containsKey(o);
 84     }
 85
 86     // 将元素(e)添加到HashSet中
 87     public boolean add(E e) {
 88         return map.put(e, PRESENT)==null;
 89     }
 90
 91     // 删除HashSet中的元素(o)
 92     public boolean remove(Object o) {
 93         return map.remove(o)==PRESENT;
 94     }
 95
 96     public void clear() {
 97         map.clear();
 98     }
 99
100     // 克隆一个HashSet,并返回Object对象
101     public Object clone() {
102         try {
103             HashSet<E> newSet = (HashSet<E>) super.clone();
104             newSet.map = (HashMap<E, Object>) map.clone();
105             return newSet;
106         } catch (CloneNotSupportedException e) {
107             throw new InternalError();
108         }
109     }
110
111     // java.io.Serializable的写入函数
112     // 将HashSet的“总的容量,加载因子,实际容量,所有的元素”都写入到输出流中
113     private void writeObject(java.io.ObjectOutputStream s)
114         throws java.io.IOException {
115         // Write out any hidden serialization magic
116         s.defaultWriteObject();
117
118         // Write out HashMap capacity and load factor
119         s.writeInt(map.capacity());
120         s.writeFloat(map.loadFactor());
121
122         // Write out size
123         s.writeInt(map.size());
124
125         // Write out all elements in the proper order.
126         for (E e : map.keySet())
127             s.writeObject(e);
128     }
129
130     // java.io.Serializable的读取函数
131     // 将HashSet的“总的容量,加载因子,实际容量,所有的元素”依次读出
132     private void readObject(java.io.ObjectInputStream s)
133         throws java.io.IOException, ClassNotFoundException {
134         // Read in any hidden serialization magic
135         s.defaultReadObject();
136
137         // Read in HashMap capacity and load factor and create backing HashMap
138         int capacity = s.readInt();
139         float loadFactor = s.readFloat();
140         map = (((HashSet)this) instanceof LinkedHashSet ?
141                new LinkedHashMap<E,Object>(capacity, loadFactor) :
142                new HashMap<E,Object>(capacity, loadFactor));
143
144         // Read in size
145         int size = s.readInt();
146
147         // Read in all elements in the proper order.
148         for (int i=0; i<size; i++) {
149             E e = (E) s.readObject();
150             map.put(e, PRESENT);
151         }
152     }
153 }

转载于:https://www.cnblogs.com/xingele0917/p/3939108.html

Java 集合系列 16 HashSet相关推荐

  1. Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例

    概要 这一章,我们对HashSet进行学习. 我们先对HashSet有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashSet.内容包括: 第1部分 HashSet介绍 第2部分 Has ...

  2. Java 集合系列16之 Spring Boot 配置文件 选项配置(一)

    springboot配置选项(一) =================================================================== COMMON SPRING ...

  3. Java 集合系列目录(Category)

    Java 集合系列目录(Category) 转自:Java 集合系列目录(Category) 01. Java 集合系列01之 总体框架 02. Java 集合系列02之 Collection架构 0 ...

  4. 新手菜鸟 Java 集合系列目录(Category)

    Java 集合系列01之 总体框架 http://www.cnblogs.com/skywang12345/p/3308498.html (笔记:Java集合是java提供的工具包,包含了常用的数据结 ...

  5. Java集合系列之四大常用集合(ArrayList、LinkedList、HashSet、HashMap)的用法

    Java集合系列之四大常用集合(ArrayList.LinkedList.HashSet.HashMap)的用法 ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是A ...

  6. Java 集合系列04之 fail-fast总结

    转载自   Java 集合系列04之 fail-fast总结 概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内 ...

  7. java集合系列——java集合概述(一)

    在JDK中集合是很重要的,学习java那么一定要好好的去了解一下集合的源码以及一些集合实现的思想! 一:集合的UML类图(网上下载的图片) Java集合工具包位置是java.util.* 二:集合工具 ...

  8. Java 集合系列02之 Collection架构

    概要 首先,我们对Collection进行说明.下面先看看Collection的一些框架类的关系图: Java 集合系列02之 Collection架构 Collection是一个接口,它主要的两个分 ...

  9. Java 集合系列06: Vector深入解析

    戳上面的蓝字关注我们哦! 精彩内容 精选java等全套视频教程 精选java电子图书 大数据视频教程精选 java项目练习精选 概论 这是接着以前的文章分享的,这里给出以前的文章的连接,供小伙伴们回顾 ...

最新文章

  1. C语言解释器的实现--存储结构(一)
  2. springer journal recommendation tool
  3. 互联网1分钟 |1116
  4. java中删除每一条数据,一条sql语句删除表中所有除ID 不同之外的记录,只留一条。...
  5. android listview快速定位,【转】android中ListView的定位:使用setSelectionFromTop实现ListView的position的保持...
  6. C语言试题八十四之求空间两点之间的距离
  7. 【WC2016】挑战NPC 【带花树】【建图】
  8. 【itext学习之路】--2.设置pdf的一些常用属性
  9. python random randint_python中random.randint(1,100)随机数中包不包括1和100
  10. memcached的缺点
  11. 向Mate 20 Pro看齐!三星S10支持无线反向充电功能
  12. 实现位数超过32bit的整数的加减乘除运算_Java 运算符
  13. 2021年十大 web hacking 技术汇总
  14. 解决VS中注释乱码的问题
  15. 服务器指定网卡进行备份数据避免影响业务口
  16. Root Pane Container(三)
  17. UniWebview Bug处理记录
  18. 微信小程序打卡签到页面(有效果图)
  19. Bmob后端云使用步骤
  20. android电话通讯录导入iphone6,怎么把小米手机通讯录导入iphone6?

热门文章

  1. Apache无法正常启动的原因
  2. vs2010 学习Silverlight学习笔记(18):JavaScript
  3. mysql 体重 类型 身高_MySQL 数据类型
  4. 提款机转账多久到账?
  5. 为什么要挖Chia币
  6. 普通二本院校的讲师可以不做科研吗?
  7. 想去三亚旅游,有什么好的景点推荐吗?
  8. 从工作到创业迈开这一步很艰难吗
  9. 为什么很多人在自媒体转不到钱?
  10. 既然光纤那么快,为什么路由器和电脑之间不用光纤连接,而还用普通网线?