ConcurrentSkipListSet基于ConcurrentSkipListMap实现的,与HashSet基于HashSet实现相像。
阅读该篇文章之前请先学习ConcurrentSkipListMap,下面我将简要介绍下ConcurrentSkipListSet实现原理。
一、代码结构
从ConcurrentSkipListSet的构造器中,可看到实例化时会初始化m对象为ConcurrentSkipListMap。
public class ConcurrentSkipListSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable {
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);
}
}
二、add方法
从下面代码看出,add的对象作为key插入了ConcurrentSkipListMap中。如果Map中有相同的对象,则不会重新设置值,这就可以避免插入重复的对象。
public boolean add(E e) {
// key为元素本身
return m.putIfAbsent(e, Boolean.TRUE) == null;
}
public V putIfAbsent(K key, V value) {
if (value == null)
throw new NullPointerException();
return doPut(key, value, true);
}
三、其他方法
基本都是直接调用ConcurrentSkipListMap的方法
public boolean remove(Object o) {
return m.remove(o, Boolean.TRUE);
}
public void clear() {
m.clear();
}
public boolean isEmpty() {
return m.isEmpty();
}
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
四、总结
ConcurrentSkipListSet可以总结出以下几点认识:
- 基于ConcurrentSkipListMap实现,同样是跳跃表的数据结构,保存对象是Map中的key。
- 值不会重复。如果跳跃表中有同样的值,则不会插入新对象。
- 遍历也是有序的。
- putAll()、size()、遍历等方法是弱一致性的,不保证原子性。