CopyOnWriteArraySet介绍

2021-10-18 09:07:39 浏览数 (1)

简介

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)添加指定元素:

代码语言:javascript复制
public boolean add(E e) {
	// 实际调用CopyOnWriteArrayList的addIfAbsent方法
	// 元素不存在,则添加,返回true;元素存在,则不添加,返回false
    return al.addIfAbsent(e);
}

可以看到,CopyOnWriteArraySet的add方法通过调用CopyOnWriteArrayList的addIfAbsent来确保元素不重复,以满足Set的特性。这块的添加也主要是通过判断是否有重复的元素。因为set是一个集合,集合是不能出现重复元素的。

总结

CopyOnWriteArraySet就是去重的CopyOnWriteArrayList,在项目并发量比较大和读多写少的情况下,并且需要去除重复元素的list的话,可以使用CopyOnWriteArraySet。

0 人点赞