简介
CopyOnWriteArraySet
为线程安全的Set
实现,它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表”实现的,而CopyOnWriteArraySet
则是通过“动态数组(CopyOnWriteArrayList
)”实现的,并不是散列表。
类结构
先来看下CopyOnWriteArraySet的类层级关系图:
代码语言:javascript复制//CopyOnWriteArraySet内部采用CopyOnWriteArrayList存储元素
private final CopyOnWriteArrayList<E> al;
和HashSet
不一样的是,CopyOnWriteArraySet
内部采用CopyOnWriteArrayList
存储元素,这也是CopyOnWriteArraySet
名字的由来,因为CopyOnWriteArrayList
是线程安全的,CopyOnWriteArraySet
的方法都是基于CopyOnWriteArrayList
实现的,所以CopyOnWriteArraySet
自然而然也是线程安全的,同样的,在并发环境下获取数据是弱一致性的。
方法解析
构造函数
代码语言:javascript复制// 空参构造函数,实际就是初始化CopyOnWriteArrayList
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
// 传入集合对象
public CopyOnWriteArraySet(Collection<? extends E> c) {
// 分两种情况
if (c.getClass() == CopyOnWriteArraySet.class) {
// 如果集合就是CopyOnWriteArraySet类型,说明数据是不重复的
// 直接全部添加到CopyOnWriteArrayList中
@SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
(CopyOnWriteArraySet<E>)c;
al = new CopyOnWriteArrayList<E>(cc.al);
}
else {
// 否则调用addAllAbsent添加所有当前集合中不存在的元素,确保数据的唯一性
al = new CopyOnWriteArrayList<E>();
al.addAllAbsent(c);
}
}
add(E e)
add(E e)
添加指定元素:
public boolean add(E e) {
// 实际调用CopyOnWriteArrayList的addIfAbsent方法
// 元素不存在,则添加,返回true;元素存在,则不添加,返回false
return al.addIfAbsent(e);
}
可以看到,CopyOnWriteArraySet的add方法通过调用CopyOnWriteArrayList的addIfAbsent来确保元素不重复,以满足Set的特性。这块的添加也主要是通过判断是否有重复的元素。因为set是一个集合,集合是不能出现重复元素的。
总结
CopyOnWriteArraySet就是去重的CopyOnWriteArrayList,在项目并发量比较大和读多写少的情况下,并且需要去除重复元素的list的话,可以使用CopyOnWriteArraySet。