傳送門:Java(Android)數(shù)據(jù)結(jié)構(gòu)匯總 -- 總綱
簡介
Set在java.util.concurrent包下的主要有CopyOnWriteArraySet和ConcurrentSkipListSet兩個實(shí)現(xiàn)類。
一、CopyOnWriteArraySet
上一章講了HashSet是一個無序的、元素不重復(fù)的、線程不安全的集合,CopyOnWriteArraySet在此基礎(chǔ)上實(shí)現(xiàn)了線程安全。也就是說它是一個無序的、元素不重復(fù)的、線程安全的集合。
CopyOnWriteArraySet內(nèi)部使用的是CopyOnWriteArrayList來實(shí)現(xiàn)的(HashSet內(nèi)部是使用HashMap來實(shí)現(xiàn)的),對CopyOnWriteArrayList不熟悉的可以看前面的章節(jié)。源碼如下:
public class CopyOnWriteArraySet<E> extends AbstractSet<E>
implements java.io.Serializable {
// 使用一個CopyOnWriteArrayList來存放元素
private final CopyOnWriteArrayList<E> al;
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
public boolean add(E e) {
// 注意這里調(diào)用的是CopyOnWriteArrayList的addIfAbsent方法,這個方法保證了元素的唯一性,
// 從而保證了CopyOnWriteArraySet的元素不重復(fù)
return al.addIfAbsent(e);
}
}
我們再來看看CopyOnWriteArrayList的addIfAbsent()方法:
public boolean addIfAbsent(E e) {
// 內(nèi)部數(shù)組
Object[] snapshot = getArray();
// indexOf方法用于在這個數(shù)組中查找要插入的元素,
// 如果找到了就返回false,否則調(diào)用addIfAbsent(e, snapshot)來進(jìn)行插入操作
return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot);
}
private boolean addIfAbsent(E e, Object[] snapshot) {
// 前面我們講了,CopyOnWriteArrayList在修改數(shù)據(jù)的時候要加鎖同步
synchronized (lock) {
Object[] current = getArray();
int len = current.length;
// 判斷數(shù)組長度是否發(fā)生了變化
if (snapshot != current) {
// Optimize for lost race to another addXXX operation
int common = Math.min(snapshot.length, len);
for (int i = 0; i < common; i++)
if (current[i] != snapshot[i] && Objects.equals(e, current[i]))
return false;
if (indexOf(e, current, common, len) >= 0)
return false;
}
Object[] newElements = Arrays.copyOf(current, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
}
}
可見,CopyOnWriteArraySet還是非常簡單的,這里就不多講。
二、ConcurrentSkipListSet
上一章講了TreeSet,它是一個有序的、元素不重復(fù)的、線程不安全的集合。ConcurrentSkipListSet在此基礎(chǔ)上增加了線程安全。也就是說它是一個有序的、元素不重復(fù)的、線程安全的集合。
ConcurrentSkipListSet內(nèi)部使用的是ConcurrentSkipListMap來實(shí)現(xiàn)的(TreeSet內(nèi)部使用的TreeMap實(shí)現(xiàn))。對ConcurrentSkipListMap不清楚的可以看第四章對Map的介紹。除了上面這些特點(diǎn)之外,其他的和TreeSet一樣。
總結(jié)
| 內(nèi)部實(shí)現(xiàn) | 元素是否重復(fù) | 元素是否有序 | 線程安全否 | 備注 | |
|---|---|---|---|---|---|
| HashSet | HashMap | 不重復(fù) | 無序 | 否 | - |
| TreeSet | TreeMap | 不重復(fù) | 有序 | 否 | - |
| ArraySet | 數(shù)組 | 不重復(fù) | 無序 | 否 | HashSet的內(nèi)存優(yōu)化版本 |
| CopyOnWriteArraySet | CopyOnWriteArrayList | 不重復(fù) | 無序 | 是 | HashSet的線程安全版本 |
| ConcurrentSkipListSet | ConcurrentSkipListMap | 不重復(fù) | 有序 | 是 | TreeSet的線程安全版本 |