摘要:介紹底層是通過來實現的,它是一個有序的線程安全的集合。源碼分析它的源碼比較簡單,跟通過實現的基本是一致,只是多了一些取最近的元素的方法。
介紹
ConcurrentSkipListSet底層是通過ConcurrentNavigableMap來實現的,它是一個有序的線程安全的集合。
源碼分析它的源碼比較簡單,跟通過Map實現的Set基本是一致,只是多了一些取最近的元素的方法。
// 實現了NavigableSet接口,并沒有所謂的ConcurrentNavigableSet接口 public class ConcurrentSkipListSetextends AbstractSet implements NavigableSet , Cloneable, java.io.Serializable { private static final long serialVersionUID = -2479143111061671589L; // 存儲使用的map private final ConcurrentNavigableMap m; // 初始化 public ConcurrentSkipListSet() { m = new ConcurrentSkipListMap (); } // 傳入比較器 public ConcurrentSkipListSet(Comparator super E> comparator) { m = new ConcurrentSkipListMap (comparator); } // 使用ConcurrentSkipListMap初始化map // 并將集合c中所有元素放入到map中 public ConcurrentSkipListSet(Collection extends E> c) { m = new ConcurrentSkipListMap (); addAll(c); } // 使用ConcurrentSkipListMap初始化map // 并將有序Set中所有元素放入到map中 public ConcurrentSkipListSet(SortedSet s) { m = new ConcurrentSkipListMap (s.comparator()); addAll(s); } // ConcurrentSkipListSet類內部返回子set時使用的 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 -------------- */ // 返回元素個數 public int size() { return m.size(); } // 檢查是否為空 public boolean isEmpty() { return m.isEmpty(); } // 檢查是否包含某個元素 public boolean contains(Object o) { return m.containsKey(o); } // 添加一個元素 // 調用map的putIfAbsent()方法 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(); } // 迭代器 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循環來比較 // 這里是有很大優化空間的,參考上篇文章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 super E> comparator() { return m.comparator(); } // 最小的元素 public E first() { return m.firstKey(); } // 最大的元素 public E last() { return m.lastKey(); } // 取兩個元素之間的子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); } // 原子操作相關內容 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實現的,雖然取子set部分是使用ConcurrentSkipListMap中的內部類,但是這些內部類其實也是和ConcurrentSkipListMap相關的,它們返回ConcurrentSkipListMap的一部分數據。
總結(1)ConcurrentSkipListSet底層是使用ConcurrentNavigableMap實現的;
(2)ConcurrentSkipListSet有序的,基于元素的自然排序或者通過比較器確定的順序;
(3)ConcurrentSkipListSet是線程安全的;
Set大匯總Set | 有序性 | 線程安全 | 底層實現 | 關鍵接口 | 特點 |
---|---|---|---|---|---|
HashSet | 無 | 否 | HashMap | 無 | 簡單 |
LinkedHashSet | 有 | 否 | LinkedHashMap | 無 | 插入順序 |
TreeSet | 有 | 否 | NavigableMap | NavigableSet | 自然順序 |
CopyOnWriteArraySet | 有 | 是 | CopyOnWriteArrayList | 無 | 插入順序,讀寫分離 |
ConcurrentSkipListSet | 有 | 是 | ConcurrentNavigableMap | NavigableSet | 自然順序 |
從中我們可以發現一些規律:
除了HashSet其它Set都是有序的;
實現了NavigableSet或者SortedSet接口的都是自然順序的;
使用并發安全的集合實現的Set也是并發安全的;
TreeSet雖然不是全部都是使用的TreeMap實現的,但其實都是跟TreeMap相關的(TreeMap的子Map中組合了TreeMap);
ConcurrentSkipListSet雖然不是全部都是使用的ConcurrentSkipListMap實現的,但其實都是跟ConcurrentSkipListMap相關的(ConcurrentSkipListeMap的子Map中組合了ConcurrentSkipListMap);
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76265.html
摘要:我們來看下的類繼承圖可以看到,實現了接口,在多線程進階二五之框架中,我們提到過實現了接口,以提供和排序相關的功能,維持元素的有序性,所以就是一種為并發環境設計的有序工具類。唯一的區別是針對的僅僅是鍵值,針對鍵值對進行操作。 showImg(https://segmentfault.com/img/bVbggic?w=960&h=600); 本文首發于一世流云專欄:https://seg...
摘要:介紹底層是使用存儲元素的,所以它并不是使用來存儲元素的。最簡單的方式就是判斷是否中的元素都在中,中的元素是否都在中,也就是兩次兩層循環。其實,并不需要。標記某個元素是否找到過,防止重復這個位置沒找到過才比較大小 介紹 CopyOnWriteArraySet底層是使用CopyOnWriteArrayList存儲元素的,所以它并不是使用Map來存儲元素的。 但是,我們知道CopyOnWri...
摘要:源碼分析屬性內部使用虛擬對象,用來作為放到中構造方法非,主要是給使用的構造方法都是調用對應的構造方法。遍歷元素直接調用的的迭代器。什么是機制是集合中的一種錯誤機制。當使用迭代器迭代時,如果發現集合有修改,則快速失敗做出響應,拋出異常。 簡介 集合,這個概念有點模糊。 廣義上來講,java中的集合是指java.util包下面的容器類,包括和Collection及Map相關的所有類。 中...
摘要:純分享直接上干貨操作系統并發支持進程管理內存管理文件系統系統進程間通信網絡通信阻塞隊列數組有界隊列鏈表無界隊列優先級有限無界隊列延時無界隊列同步隊列隊列內存模型線程通信機制內存共享消息傳遞內存模型順序一致性指令重排序原則內存語義線程 純分享 , 直接上干貨! 操作系統并發支持 進程管理內存管...
摘要:就有這個功能,它是怎么實現有序的呢源碼分析繼承自,讓我們直接上源碼來看看它們有什么不同。是有序的,它是按照插入的順序排序的。所以,是不支持按訪問順序對元素排序的,只能按插入順序排序。 介紹 上一節我們說HashSet中的元素是無序的,那么有沒有什么辦法保證Set中的元素是有序的呢? 答案是當然可以。 LinkedHashSet就有這個功能,它是怎么實現有序的呢? 源碼分析 Linked...
閱讀 2815·2021-10-13 09:48
閱讀 3776·2021-10-13 09:39
閱讀 3586·2021-09-22 16:04
閱讀 1816·2021-09-03 10:48
閱讀 837·2021-08-03 14:04
閱讀 2358·2019-08-29 15:18
閱讀 3400·2019-08-26 12:19
閱讀 2869·2019-08-26 12:08