成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[學(xué)習(xí)筆記-Java集合-13] Set - ConcurrentSkipListSet源碼分析

yunhao / 2733人閱讀

摘要:介紹底層是通過來(lái)實(shí)現(xiàn)的,它是一個(gè)有序的線程安全的集合。源碼分析它的源碼比較簡(jiǎn)單,跟通過實(shí)現(xiàn)的基本是一致,只是多了一些取最近的元素的方法。

介紹

ConcurrentSkipListSet底層是通過ConcurrentNavigableMap來(lái)實(shí)現(xiàn)的,它是一個(gè)有序的線程安全的集合。

源碼分析

它的源碼比較簡(jiǎn)單,跟通過Map實(shí)現(xiàn)的Set基本是一致,只是多了一些取最近的元素的方法。

// 實(shí)現(xiàn)了NavigableSet接口,并沒有所謂的ConcurrentNavigableSet接口
public class ConcurrentSkipListSet
    extends AbstractSet
    implements NavigableSet, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2479143111061671589L;

    // 存儲(chǔ)使用的map
    private final ConcurrentNavigableMap m;

    // 初始化
    public ConcurrentSkipListSet() {
        m = new ConcurrentSkipListMap();
    }

    // 傳入比較器
    public ConcurrentSkipListSet(Comparator comparator) {
        m = new ConcurrentSkipListMap(comparator);
    }

    // 使用ConcurrentSkipListMap初始化map
    // 并將集合c中所有元素放入到map中
    public ConcurrentSkipListSet(Collection c) {
        m = new ConcurrentSkipListMap();
        addAll(c);
    }

    // 使用ConcurrentSkipListMap初始化map
    // 并將有序Set中所有元素放入到map中
    public ConcurrentSkipListSet(SortedSet s) {
        m = new ConcurrentSkipListMap(s.comparator());
        addAll(s);
    }

    // ConcurrentSkipListSet類內(nèi)部返回子set時(shí)使用的
    ConcurrentSkipListSet(ConcurrentNavigableMap m) {
        this.m = m;
    }

    // 克隆方法
    public ConcurrentSkipListSet clone() {
        try {
            @SuppressWarnings("unchecked")
            ConcurrentSkipListSet clone =
                (ConcurrentSkipListSet) super.clone();
            clone.setMap(new ConcurrentSkipListMap(m));
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }

    /* ---------------- Set operations -------------- */
    // 返回元素個(gè)數(shù)
    public int size() {
        return m.size();
    }

    // 檢查是否為空
    public boolean isEmpty() {
        return m.isEmpty();
    }

    // 檢查是否包含某個(gè)元素
    public boolean contains(Object o) {
        return m.containsKey(o);
    }

    // 添加一個(gè)元素
    // 調(diào)用map的putIfAbsent()方法
    public boolean add(E e) {
        return m.putIfAbsent(e, Boolean.TRUE) == null;
    }

    // 移除一個(gè)元素
    public boolean remove(Object o) {
        return m.remove(o, Boolean.TRUE);
    }

    // 清空所有元素
    public void clear() {
        m.clear();
    }

    // 迭代器
    public Iterator iterator() {
        return m.navigableKeySet().iterator();
    }

    // 降序迭代器
    public Iterator descendingIterator() {
        return m.descendingKeySet().iterator();
    }


    /* ---------------- AbstractSet Overrides -------------- */
    // 比較相等方法
    public boolean equals(Object o) {
        // Override AbstractSet version to avoid calling size()
        if (o == this)
            return true;
        if (!(o instanceof Set))
            return false;
        Collection c = (Collection) o;
        try {
            // 這里是通過兩次兩層for循環(huán)來(lái)比較
            // 這里是有很大優(yōu)化空間的,參考上篇文章CopyOnWriteArraySet中的彩蛋
            return containsAll(c) && c.containsAll(this);
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }
    }

    // 移除集合c中所有元素
    public boolean removeAll(Collection c) {
        // Override AbstractSet version to avoid unnecessary call to size()
        boolean modified = false;
        for (Object e : c)
            if (remove(e))
                modified = true;
        return modified;
    }

    /* ---------------- Relational operations -------------- */

    // 小于e的最大元素
    public E lower(E e) {
        return m.lowerKey(e);
    }

    // 小于等于e的最大元素
    public E floor(E e) {
        return m.floorKey(e);
    }

    // 大于等于e的最小元素
    public E ceiling(E e) {
        return m.ceilingKey(e);
    }

    // 大于e的最小元素
    public E higher(E e) {
        return m.higherKey(e);
    }

    // 彈出最小的元素
    public E pollFirst() {
        Map.Entry e = m.pollFirstEntry();
        return (e == null) ? null : e.getKey();
    }

    // 彈出最大的元素
    public E pollLast() {
        Map.Entry e = m.pollLastEntry();
        return (e == null) ? null : e.getKey();
    }


    /* ---------------- SortedSet operations -------------- */

    // 取比較器
    public Comparator comparator() {
        return m.comparator();
    }

    // 最小的元素
    public E first() {
        return m.firstKey();
    }

    // 最大的元素
    public E last() {
        return m.lastKey();
    }

    // 取兩個(gè)元素之間的子set
    public NavigableSet subSet(E fromElement,
                                  boolean fromInclusive,
                                  E toElement,
                                  boolean toInclusive) {
        return new ConcurrentSkipListSet
            (m.subMap(fromElement, fromInclusive,
                      toElement,   toInclusive));
    }

    // 取頭子set
    public NavigableSet headSet(E toElement, boolean inclusive) {
        return new ConcurrentSkipListSet(m.headMap(toElement, inclusive));
    }

    // 取尾子set
    public NavigableSet tailSet(E fromElement, boolean inclusive) {
        return new ConcurrentSkipListSet(m.tailMap(fromElement, inclusive));
    }

    // 取子set,包含from,不包含to
    public NavigableSet subSet(E fromElement, E toElement) {
        return subSet(fromElement, true, toElement, false);
    }

    // 取頭子set,不包含to
    public NavigableSet headSet(E toElement) {
        return headSet(toElement, false);
    }

    // 取尾子set,包含from
    public NavigableSet tailSet(E fromElement) {
        return tailSet(fromElement, true);
    }

    // 降序set
    public NavigableSet descendingSet() {
        return new ConcurrentSkipListSet(m.descendingMap());
    }

    // 可分割的迭代器
    @SuppressWarnings("unchecked")
    public Spliterator spliterator() {
        if (m instanceof ConcurrentSkipListMap)
            return ((ConcurrentSkipListMap)m).keySpliterator();
        else
            return (Spliterator)((ConcurrentSkipListMap.SubMap)m).keyIterator();
    }

    // 原子更新map,給clone方法使用
    private void setMap(ConcurrentNavigableMap map) {
        UNSAFE.putObjectVolatile(this, mapOffset, map);
    }

    // 原子操作相關(guān)內(nèi)容
    private static final sun.misc.Unsafe UNSAFE;
    private static final long mapOffset;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class k = ConcurrentSkipListSet.class;
            mapOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("m"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
}

可以看到,ConcurrentSkipListSet基本上都是使用ConcurrentSkipListMap實(shí)現(xiàn)的,雖然取子set部分是使用ConcurrentSkipListMap中的內(nèi)部類,但是這些內(nèi)部類其實(shí)也是和ConcurrentSkipListMap相關(guān)的,它們返回ConcurrentSkipListMap的一部分?jǐn)?shù)據(jù)。

總結(jié)

(1)ConcurrentSkipListSet底層是使用ConcurrentNavigableMap實(shí)現(xiàn)的;

(2)ConcurrentSkipListSet有序的,基于元素的自然排序或者通過比較器確定的順序;

(3)ConcurrentSkipListSet是線程安全的;

Set大匯總
Set 有序性 線程安全 底層實(shí)現(xiàn) 關(guān)鍵接口 特點(diǎn)
HashSet 無(wú) HashMap 無(wú) 簡(jiǎn)單
LinkedHashSet LinkedHashMap 無(wú) 插入順序
TreeSet NavigableMap NavigableSet 自然順序
CopyOnWriteArraySet CopyOnWriteArrayList 無(wú) 插入順序,讀寫分離
ConcurrentSkipListSet ConcurrentNavigableMap NavigableSet 自然順序

從中我們可以發(fā)現(xiàn)一些規(guī)律:

除了HashSet其它Set都是有序的;

實(shí)現(xiàn)了NavigableSet或者SortedSet接口的都是自然順序的;

使用并發(fā)安全的集合實(shí)現(xiàn)的Set也是并發(fā)安全的;

TreeSet雖然不是全部都是使用的TreeMap實(shí)現(xiàn)的,但其實(shí)都是跟TreeMap相關(guān)的(TreeMap的子Map中組合了TreeMap);

ConcurrentSkipListSet雖然不是全部都是使用的ConcurrentSkipListMap實(shí)現(xiàn)的,但其實(shí)都是跟ConcurrentSkipListMap相關(guān)的(ConcurrentSkipListeMap的子Map中組合了ConcurrentSkipListMap);

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76265.html

相關(guān)文章

  • Java多線程進(jìn)階(二六)—— J.U.C之collections框架:ConcurrentSkip

    摘要:我們來(lái)看下的類繼承圖可以看到,實(shí)現(xiàn)了接口,在多線程進(jìn)階二五之框架中,我們提到過實(shí)現(xiàn)了接口,以提供和排序相關(guān)的功能,維持元素的有序性,所以就是一種為并發(fā)環(huán)境設(shè)計(jì)的有序工具類。唯一的區(qū)別是針對(duì)的僅僅是鍵值,針對(duì)鍵值對(duì)進(jìn)行操作。 showImg(https://segmentfault.com/img/bVbggic?w=960&h=600); 本文首發(fā)于一世流云專欄:https://seg...

    levius 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記-Java集合-12] Set - CopyOnWriteArraySet源碼分析

    摘要:介紹底層是使用存儲(chǔ)元素的,所以它并不是使用來(lái)存儲(chǔ)元素的。最簡(jiǎn)單的方式就是判斷是否中的元素都在中,中的元素是否都在中,也就是兩次兩層循環(huán)。其實(shí),并不需要。標(biāo)記某個(gè)元素是否找到過,防止重復(fù)這個(gè)位置沒找到過才比較大小 介紹 CopyOnWriteArraySet底層是使用CopyOnWriteArrayList存儲(chǔ)元素的,所以它并不是使用Map來(lái)存儲(chǔ)元素的。 但是,我們知道CopyOnWri...

    Lin_YT 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記-Java集合-9] Set - HashSet源碼分析

    摘要:源碼分析屬性內(nèi)部使用虛擬對(duì)象,用來(lái)作為放到中構(gòu)造方法非,主要是給使用的構(gòu)造方法都是調(diào)用對(duì)應(yīng)的構(gòu)造方法。遍歷元素直接調(diào)用的的迭代器。什么是機(jī)制是集合中的一種錯(cuò)誤機(jī)制。當(dāng)使用迭代器迭代時(shí),如果發(fā)現(xiàn)集合有修改,則快速失敗做出響應(yīng),拋出異常。 簡(jiǎn)介 集合,這個(gè)概念有點(diǎn)模糊。 廣義上來(lái)講,java中的集合是指java.util包下面的容器類,包括和Collection及Map相關(guān)的所有類。 中...

    kohoh_ 評(píng)論0 收藏0
  • 阿里 2021 版最全 Java 并發(fā)編程筆記,看完我才懂了“內(nèi)卷”的真正意義

    摘要:純分享直接上干貨操作系統(tǒng)并發(fā)支持進(jìn)程管理內(nèi)存管理文件系統(tǒng)系統(tǒng)進(jìn)程間通信網(wǎng)絡(luò)通信阻塞隊(duì)列數(shù)組有界隊(duì)列鏈表無(wú)界隊(duì)列優(yōu)先級(jí)有限無(wú)界隊(duì)列延時(shí)無(wú)界隊(duì)列同步隊(duì)列隊(duì)列內(nèi)存模型線程通信機(jī)制內(nèi)存共享消息傳遞內(nèi)存模型順序一致性指令重排序原則內(nèi)存語(yǔ)義線程 純分享 , 直接上干貨! 操作系統(tǒng)并發(fā)支持 進(jìn)程管理內(nèi)存管...

    不知名網(wǎng)友 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記-Java集合-10] Set - LinkedHashSet源碼分析

    摘要:就有這個(gè)功能,它是怎么實(shí)現(xiàn)有序的呢源碼分析繼承自,讓我們直接上源碼來(lái)看看它們有什么不同。是有序的,它是按照插入的順序排序的。所以,是不支持按訪問順序?qū)υ嘏判虻?,只能按插入順序排序? 介紹 上一節(jié)我們說(shuō)HashSet中的元素是無(wú)序的,那么有沒有什么辦法保證Set中的元素是有序的呢? 答案是當(dāng)然可以。 LinkedHashSet就有這個(gè)功能,它是怎么實(shí)現(xiàn)有序的呢? 源碼分析 Linked...

    ThreeWords 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<