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

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

簡(jiǎn)介

Setjava.util.concurrent包下的主要有CopyOnWriteArraySetConcurrentSkipListSet兩個(gè)實(shí)現(xiàn)類。

一、CopyOnWriteArraySet

上一章講了HashSet是一個(gè)無(wú)序的、元素不重復(fù)的、線程不安全的集合,CopyOnWriteArraySet在此基礎(chǔ)上實(shí)現(xiàn)了線程安全。也就是說(shuō)它是一個(gè)無(wú)序的、元素不重復(fù)的、線程安全的集合。

CopyOnWriteArraySet內(nèi)部使用的是CopyOnWriteArrayList來(lái)實(shí)現(xiàn)的(HashSet內(nèi)部是使用HashMap來(lái)實(shí)現(xiàn)的),對(duì)CopyOnWriteArrayList不熟悉的可以看前面的章節(jié)。源碼如下:

public class CopyOnWriteArraySet<E> extends AbstractSet<E>
        implements java.io.Serializable {

    // 使用一個(gè)CopyOnWriteArrayList來(lái)存放元素
    private final CopyOnWriteArrayList<E> al;

    public CopyOnWriteArraySet() {
        al = new CopyOnWriteArrayList<E>();
    }

    public boolean add(E e) {
        // 注意這里調(diào)用的是CopyOnWriteArrayList的addIfAbsent方法,這個(gè)方法保證了元素的唯一性,
        // 從而保證了CopyOnWriteArraySet的元素不重復(fù)
        return al.addIfAbsent(e);
    }
}

我們?cè)賮?lái)看看CopyOnWriteArrayList的addIfAbsent()方法:

public boolean addIfAbsent(E e) {
    // 內(nèi)部數(shù)組
    Object[] snapshot = getArray();

    // indexOf方法用于在這個(gè)數(shù)組中查找要插入的元素,
    // 如果找到了就返回false,否則調(diào)用addIfAbsent(e, snapshot)來(lái)進(jìn)行插入操作
    return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot);
}

private boolean addIfAbsent(E e, Object[] snapshot) {
    // 前面我們講了,CopyOnWriteArrayList在修改數(shù)據(jù)的時(shí)候要加鎖同步
    synchronized (lock) {
        Object[] current = getArray();
        int len = current.length;
        // 判斷數(shù)組長(zhǎng)度是否發(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還是非常簡(jiǎn)單的,這里就不多講。

二、ConcurrentSkipListSet

上一章講了TreeSet,它是一個(gè)有序的、元素不重復(fù)的、線程不安全的集合。ConcurrentSkipListSet在此基礎(chǔ)上增加了線程安全。也就是說(shuō)它是一個(gè)有序的、元素不重復(fù)的、線程安全的集合。

ConcurrentSkipListSet內(nèi)部使用的是ConcurrentSkipListMap來(lái)實(shí)現(xiàn)的(TreeSet內(nèi)部使用的TreeMap實(shí)現(xiàn))。對(duì)ConcurrentSkipListMap不清楚的可以看第四章對(duì)Map的介紹。除了上面這些特點(diǎn)之外,其他的和TreeSet一樣。

總結(jié)

內(nèi)部實(shí)現(xiàn) 元素是否重復(fù) 元素是否有序 線程安全否 備注
HashSet HashMap 不重復(fù) 無(wú)序 -
TreeSet TreeMap 不重復(fù) 有序 -
ArraySet 數(shù)組 不重復(fù) 無(wú)序 HashSet的內(nèi)存優(yōu)化版本
CopyOnWriteArraySet CopyOnWriteArrayList 不重復(fù) 無(wú)序 HashSet的線程安全版本
ConcurrentSkipListSet ConcurrentSkipListMap 不重復(fù) 有序 TreeSet的線程安全版本
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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

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