概述
HashSet也是一个使用频率非常高的一个集合容器,最大的特点是存储的元素是没有重复的,而且是无序的,那么对于HashSet是如何判断原始是否重复、底层又是怎么实现的,你了解吗?
HashSet介绍
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
- 集合中的元素不重复
- 允许有null值
- 是无序的,即不会记录插入的顺序
- 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的
以上是HashSet的类结构图:
- 实现了Set接口,表名是一个去重集合容器
- 直接继承了AbstractSet类,该类实现了Set的骨干操作
- 实现了Cloneable接口,标记该类可以进行clone操作
- 实现了Serializable接口,标记改类可以序列化
构造方法
- public HashSet()
说明: 创建一个默认为空的HashSet
- public HashSet(int initialCapacity, float loadFactor)
说明:创建一个HashSet容器,initialCapacity表示设置初始容量大小,loadFactor表示负载因子, 当容量达到最大容量*负载因子时,需要进行扩容,这属于HashMap的知识。
- public HashSet(Collection<? extends E> c)
说明:创建一个容器内容为c的集合
关键方法
- public boolean add(E e)
说明:向集合中添加元素
- public boolean remove(Object o)
说明:向集合中删除元素
- public void clear()
说明:清空集合元素
- public int size()
说明:返回集合中元素的数量
使用案例
@Test public void test1() { Set<String> set = new HashSet<>(); set.add("a"); set.add("b"); set.add("a"); set.add("c"); // 添加了4个元素,size = 3 System.out.println(set.size()); System.out.println(set); }
运行结果:
小结: 说明重复的元素不会被添加到集合中。
核心机制
实现原理
HashSet的实现原理是基于HashMap实现的,关键是要了解HashMap的实现原理,我们下文主要从源码说明HashSet的确是走的HashMap的逻辑。
如何判断元素是否是一致
HashSet最大的特点是集合中的元素不重复,那它是根据什么判断是否重复,或者是同一个元素呢?大致逻辑如下:
当你把对象加入到HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的hashcode值作比较,如果没有相符的hashcode值,HashSet会假设对象没有重复出现,但是如果发现有相同hashcode值的对象,这时会调用equals()方法来来检查hashcode相等的对象是否真的相同,如果两者相同,HashSet就不会加入操作成功。
源码解析
主要看下add方法
// HashSet的add方法 public boolean add(E e) { // 调用map的put方法 return map.put(e, PRESENT)==null; }
定义了一个HashMap的属性,如下
所以说明HashSet的底层实现就是HashMap,只不过只关注map的key部分。
总结
HashSet是一个很有用的容器,最大的特点是集合中的元素都是不重复的,底层实现是基于HashMap,所以关键是要了解HashMap的实现机制。