引:如果用来有个去重的需求,你肯定会想到用HashSet,那我们看看它的实现!
详细注释:源码分析地址
概览
它是由哈希表(实际上是一个HashMap实例)支持,是不是有点意思?它不保证set的迭代顺序,有且只允许一个null元素,当然其他元素不能重复。
它不是同步容器。如果多个线程同时访问一个哈希set,而其中至少一个线程修改了该 set,那么它必须保持外部同步。这通常是通过对自然封装该set的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该set进行意外的不同步访问。
所有这个类的方法返回的迭代器都是快速失败的 :如果映射在迭代器创建之后的任何时间被结构地修改,除了通过迭代器自己的remove方法之外,迭代器将抛出一个ConcurrentModificationException。(老生长谈)
构造
关于HashSet的操作(下面都是),基本上都是直接调用底层HashMap的相关方法来完成。所以在后面参考找到自己关于HashMap的文章。1
2
3
4
5
6
7
8
9// 真的操作的执行者
private transient HashMap<E,Object> map;
// 定义一个"虚拟"的Object对象作为HashMap的value
private static final Object PRESENT = new Object();
// 构造HashMap
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
增
在HashMap新增一个键值对1
2
3public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
删
在HashMap删除一个键值对1
2
3public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
查
在HashMap查找key是否存在1
2
3public boolean contains(Object o) {
return map.containsKey(o);
}
总结
水文一篇,只要记住一点,就是只要理解了HashMap,HashSet is so easy!!