博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java集合之ConcurrentSkipListSet源码分析——Set大汇总
阅读量:6306 次
发布时间:2019-06-22

本文共 6641 字,大约阅读时间需要 22 分钟。

java集合之ConcurrentSkipListSet源码分析——Set大汇总

问题
(1)ConcurrentSkipListSet的底层是ConcurrentSkipListMap吗?

(2)ConcurrentSkipListSet是线程安全的吗?

(3)ConcurrentSkipListSet是有序的吗?

(4)ConcurrentSkipListSet和之前讲的Set有何不同?

简介

ConcurrentSkipListSet底层是通过ConcurrentNavigableMap来实现的,它是一个有序的线程安全的集合。

源码分析

它的源码比较简单,跟通过Map实现的Set基本是一致,只是多了一些取最近的元素的方法。

为了保持专栏的完整性,我还是贴一下源码,最后会对Set的整个家族作一个对比,有兴趣的可以直接拉到最下面。

// 实现了NavigableSet接口,并没有所谓的ConcurrentNavigableSet接口

public class ConcurrentSkipListSet

extends AbstractSet
implements NavigableSet
, Cloneable, java.io.Serializable {private static final long serialVersionUID = -2479143111061671589L;// 存储使用的mapprivate 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类内部返回子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
comparator() { return m.comparator();}// 最小的元素public E first() { return m.firstKey();}// 最大的元素public E last() { return m.lastKey();}// 取两个元素之间的子setpublic NavigableSet
subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new ConcurrentSkipListSet
(m.subMap(fromElement, fromInclusive, toElement, toInclusive));}// 取头子setpublic NavigableSet
headSet(E toElement, boolean inclusive) { return new ConcurrentSkipListSet
(m.headMap(toElement, inclusive));}// 取尾子setpublic NavigableSet
tailSet(E fromElement, boolean inclusive) { return new ConcurrentSkipListSet
(m.tailMap(fromElement, inclusive));}// 取子set,包含from,不包含topublic NavigableSet
subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false);}// 取头子set,不包含topublic NavigableSet
headSet(E toElement) { return headSet(toElement, false);}// 取尾子set,包含frompublic NavigableSet
tailSet(E fromElement) { return tailSet(fromElement, true);}// 降序setpublic 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的一部分数据。

另外,这里的equals()方法实现的相当敷衍,有很大的优化空间,作者这样实现,应该也是知道几乎没有人来调用equals()方法吧。

总结

(1)ConcurrentSkipListSet底层是使用ConcurrentNavigableMap实现的;

(2)ConcurrentSkipListSet有序的,基于元素的自然排序或者通过比较器确定的顺序;

(3)ConcurrentSkipListSet是线程安全的;

彩蛋

Set大汇总:

Set 有序性 线程安全 底层实现 关键接口 特点

HashSet 无 否 HashMap 无 简单
LinkedHashSet 有 否 LinkedHashMap 无 插入顺序
TreeSet 有 否 NavigableMap NavigableSet 自然顺序
CopyOnWriteArraySet 有 是 CopyOnWriteArrayList 无 插入顺序,读写分离
ConcurrentSkipListSet 有 是 ConcurrentNavigableMap NavigableSet 自然顺序
从中我们可以发现一些规律:

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

(2)实现了NavigableSet或者SortedSet接口的都是自然顺序的;

(3)使用并发安全的集合实现的Set也是并发安全的;

(4)TreeSet虽然不是全部都是使用的TreeMap实现的,但其实都是跟TreeMap相关的(TreeMap的子Map中组合了TreeMap);

(5)ConcurrentSkipListSet虽然不是全部都是使用的ConcurrentSkipListMap实现的,但其实都是跟ConcurrentSkipListMap相关的(ConcurrentSkipListeMap的子Map中组合了ConcurrentSkipListMap);

原文地址

转载地址:http://jhixa.baihongyu.com/

你可能感兴趣的文章
Linux 下添加用户,修改权限
查看>>
请问view controller scene,该如何删除
查看>>
bootstrap新闻模块样式模板
查看>>
zzzzw_在线考试系统①准备篇
查看>>
App Store 审核被拒的23个理由
查看>>
剑指offer第二版-1.赋值运算符函数
查看>>
javascript 对象
查看>>
Android学习笔记——文件路径(/mnt/sdcard/...)、Uri(content://media/external/...)学习
查看>>
Echart:前端很好的数据图表展现工具+demo
查看>>
CATransform3D iOS动画特效详解
查看>>
Linux VNC黑屏(转)
查看>>
Java反射简介
查看>>
react脚手架应用以及iview安装
查看>>
shell学习之用户管理和文件属性
查看>>
day8--socket网络编程进阶
查看>>
node mysql模块写入中文字符时的乱码问题
查看>>
仍需"敬请期待"的微信沃卡
查看>>
分析Ajax爬取今日头条街拍美图
查看>>
内存分布简视图
查看>>
POJ 2918 求解数独
查看>>