Java(Android)數(shù)據(jù)結(jié)構(gòu)匯總(二)-- Set(下)

傳送門:Java(Android)數(shù)據(jù)結(jié)構(gòu)匯總 -- 總綱

簡介

Setjava.util.concurrent包下的主要有CopyOnWriteArraySetConcurrentSkipListSet兩個實(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的線程安全版本
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 上一篇文章介紹了Set集合的通用知識。Set集合中包含了三個比較重要的實(shí)現(xiàn)類:HashSet、TreeSet和En...
    Ruheng閱讀 16,124評論 3 57
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,644評論 0 3
  • 明明你自己考試得了77分,覺得挺滿意的,然而你看到班上的同學(xué)個個都是八十多分,那你就不會開心起來了。與其說是為了讓...
    煙雨蕭蕭閱讀 247評論 0 0
  • 有點(diǎn)不習(xí)慣喝酒到這種程度。畢竟之前不是實(shí)在不到位就是著實(shí)喝大了,今次酒后除寫完洋洋一大篇日記,還惦記著發(fā)散一些個人...
    鹿羽閱讀 444評論 0 3
  • 何為“未知”,也就是“不知道”,也許有人說,你這不是廢話嗎?是的,單純看字面釋義確實(shí)確實(shí)對不起這一番解釋,但我們著...
    倉頡書閱讀 667評論 0 0

友情鏈接更多精彩內(nèi)容