HashSet 类注释
这个类实现了Set接口,由一个哈希表(实际上是一个HashMap实例)支持。它不保证集合的迭代顺序;特别是,它不能保证订单在一段时间内保持不变。此类允许使用null元素。
这个类为基本操作(添加、删除、包含和大小)提供了恒定的时间性能,假设哈希函数将元素正确地分散在存储桶中。
在此集合上迭代需要与HashSet实例的大小(元素数量)加上支持HashMap实例的“容量”(存储桶数量)之和成比例的时间。
因此,如果迭代性能很重要,那么不要将初始容量设置得太高(或负载系数设置得太低),这一点非常重要。
请注意,此实现不是同步的。如果多个线程同时访问一个哈希集,并且至少有一个线程修改了该集,则必须对其进行外部同步。这通常是通过对一些自然封装集合的对象进行同步来实现的。如果不存在这样的对象,则应使用Collections“包装”集合。synchronizedSet方法。最好在创建时执行此操作,以防止意外地对集合进行不同步的访问:
设置s=集合。synchronizedSet(new HashSet(…));
此类迭代器方法返回的迭代器是快速失效的:如果在迭代器创建后的任何时候,以除迭代器自己的remove方法之外的任何方式修改集合,则迭代器将抛出ConcurrentModificationException。因此,面对并发修改,迭代器会迅速而干净地失败,而不是冒着在未来不确定的时间出现任意、不确定行为的风险。
请注意,迭代器的快速失效行为是无法保证的,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。故障快速迭代器在尽力而为的基础上抛出ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速故障行为应该只用于检测错误。
此类是Java Collections Framework的成员。
1、HashSet 定义
HashSet 是一个由 HashMap 实现的集合。元素无序且不能重复。
相对于早期版本的 JDK HashMap 实现,新增了红黑树作为底层数据结构,在数据量较大且哈希碰撞较多时,能够极大的增加检索的效率。
HashMap 作为底层数据结构实现的一种数据结构——HashSet
public class HashSet extends AbstractSet implements Set, Cloneable, java.io.Serializable {
........
}
和前面介绍的大多数集合一样,HashSet 也实现了 Cloneable 接口和 Serializable 接口,分别用来支持克隆以及支持序列化。还实现了 Set 接口,该接口定义了 Set 集合类型的一套规范。
2、字段属性
//HashSet集合中的内容是通过 HashMap 数据结构来存储的
private transient HashMap map;
//向HashSet中添加数据,数据在上面的 map 结构是作为 key 存在的,而value统一都是 PRESENT persent
private static final Object PRESENT = new Object();
第一个定义一个 HashMap,作为实现 HashSet 的数据结构
第二个 PRESENT 对象,因为前面讲过 HashMap 是作为键值对 key-value 进行存储的,而 HashSet 不是键值对,
那么选择 HashMap 作为实现,其原理就是存储在 HashSet 中的数据 作为 Map 的 key,而 Map 的value
统一为 PRESENT(下面介绍具体实现时会了解)。
3、构造函数
无参构造
public HashSet() {
map = new HashMap<>();
}
直接 new 一个 HashMap 对象出来,采用无参的 HashMap 构造函数,具有默认初始容量(16)和加载因子(0.75)。
指定初始容量
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
指定初始容量和加载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
构造包含指定集合中的元素
public HashSet(Collection c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
4、添加元素
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
通过 map.put() 方法来添加元素,说明了该方法如果新插入的key不存在,则返回null,如果新插入的key存在,则返回原key对应的value值(注意新插入的value会覆盖原value值)。
也就是说 HashSet 的 add(E e) 方法,会将 e 作为 key,PRESENT 作为 value 插入到 map 集合中,
如果 e 不存在,则插入成功返回 true;如果存在,则返回false。
5、删除元素
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
调用 HashMap 的remove(Object o) 方法,该方法会首先查找 map 集合中是否存在 o ,如果存在则删除,并返回该值,
如果不存在则返回 null。也就是说 HashSet 的 remove(Object o) 方法,删除成功返回 true,删除的元素不存在会返回 false。
6、查找元素
public boolean contains(Object o) {
return map.containsKey(o);
}
调用 HashMap 的 containsKey(Object o) 方法,找到了返回 true,找不到返回 false。
7、遍历元素
HashSet set = new HashSet<>();
set.add(1);
set.add(2);
//增强for循环
for( Integer i : set ) {
System.out.println(i);
}
//普通for循环
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
1840

被折叠的 条评论
为什么被折叠?



