Java多線程進階(二六)—— J.U.C之collections框架:ConcurrentSkipListSet

圖片描述

本文首發於一世流雲專欄: https://segmentfault.com/blog...

1、ConcurrentSkipListSet簡介

ConcurrentSkipListSet,是JDK1.6時J.U.C新增的一個集合工具類,顧名思義,它是一種SET類型。java

SET類型,在數學上稱爲「集合」,具備互異性、無序性的特色,也就是說SET中的任意兩個元素均不相同(即不包含重複元素),且元素是無序的。

是否是感受和HashMap有點相似?HashMap中的Key也是不能重複,且是無序的。segmentfault

事實上,JDK提供的默認SET實現——HashSet,其實就是採用「組合」的方式——內部引用了一個HashMap對象,以此實現SET的功能。數據結構

咱們來看下ConcurrentSkipListSet的類繼承圖:
clipboard.png多線程

能夠看到,ConcurrentSkipListSet實現了NavigableSet接口,在Java多線程進階(二五)—— J.U.C之collections框架:ConcurrentSkipListMap中,咱們提到過ConcurrentSkipListMap實現了NavigableMap接口,以提供和排序相關的功能,維持元素的有序性,因此ConcurrentSkipListSet就是一種爲併發環境設計的有序SET工具類。併發

clipboard.png

NavigableSet的功能和 NavigableMap幾乎是徹底同樣的,提供了根據指定Key返回最接近項、按升序/降序返回全部鍵的視圖等功能。惟一的區別是NavigableSet針對的僅僅是鍵值,NavigableMap針對鍵值對進行操做。

2、ConcurrentSkipListSet原理

內部結構

ConcurrentSkipListSet的實現很是簡單,其內部引用了一個ConcurrentSkipListMap對象,全部API方法均委託ConcurrentSkipListMap對象完成:框架

public class ConcurrentSkipListSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable {

    /**
     * The underlying map. Uses Boolean.TRUE as value for each
     * element.  This field is declared final for the sake of thread
     * safety, which entails some ugliness in clone().
     */
    private final ConcurrentNavigableMap<E, Object> m;

    public ConcurrentSkipListSet() {
        m = new ConcurrentSkipListMap<E, Object>();
    }

    public ConcurrentSkipListSet(Comparator<? super E> comparator) {
        m = new ConcurrentSkipListMap<E, Object>(comparator);
    }

    public ConcurrentSkipListSet(Collection<? extends E> c) {
        m = new ConcurrentSkipListMap<E, Object>();
        addAll(c);
    }

    public ConcurrentSkipListSet(SortedSet<E> s) {
        m = new ConcurrentSkipListMap<E, Object>(s.comparator());
        addAll(s);
    }

    ConcurrentSkipListSet(ConcurrentNavigableMap<E, Object> m) {
        this.m = m;
    }
    
    // ...
}

從上述代碼能夠看出,ConcurrentSkipListSet在構造時建立了一個ConcurrentSkipListMap對象,並由字段m引用,因此其實ConcurrentSkipListSet就是一種跳錶類型的數據結構,其平均增刪改查的時間複雜度均爲O(logn)工具

核心方法

咱們來看下ConcurrentSkipListSet是如何實現API方法的:this

public int size() {
    return m.size();
}

public boolean isEmpty() {
    return m.isEmpty();
}

public boolean contains(Object o) {
    return m.containsKey(o);
}


public boolean add(E e) {
    return m.putIfAbsent(e, Boolean.TRUE) == null;
}

public boolean remove(Object o) {
    return m.remove(o, Boolean.TRUE);
}

public void clear() {
    m.clear();
}
 
//...

從上述代碼能夠看出,全部操做均是委託ConcurrentSkipListMap對象完成的。重點看下add方法:spa

public boolean add(E e) {
    return m.putIfAbsent(e, Boolean.TRUE) == null;
}

咱們知道ConcurrentSkipListMap對鍵值對的要求是均不能爲null,因此ConcurrentSkipListSet在插入元素的時候,用一個Boolean.TRUE對象(至關於一個值爲true的Boolean型對象)做爲value,同時putIfAbsent能夠保證不會存在相同的Key。線程

因此,最終跳錶中的全部Node結點的Key均不會相同,且值都是Boolean.True

相關文章
相關標籤/搜索