problem
(1) Is the bottom of the ConcurrentSkipListSet a ConcurrentSkipListMap?
(2) Is the ConcurrentSkipListSet thread safe?
(3) Is the ConcurrentSkipListSet ordered?
(4) How is the ConcurrentSkipListSet different from the previous Set?
brief introduction
The bottom level of the ConcurrentSkipListSet is implemented through ConcurrentNavigableMap, which is an ordered collection of thread security.
Source Code Analysis
Its source code is simple, basically identical to the Set implemented through Map, but there are a few more ways to get the closest element.
To preserve the integrity of the column, I'll stick to the source code and finally compare the entire family of Set s, pulling those interested directly to the bottom.
// Implements the NavigableSet interface without the so-called ConcurrentNavigableSet interface public class ConcurrentSkipListSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable { private static final long serialVersionUID = -2479143111061671589L; // Store map s used private final ConcurrentNavigableMap<E,Object> m; // Initialization public ConcurrentSkipListSet() { m = new ConcurrentSkipListMap<E,Object>(); } // Incoming Comparator public ConcurrentSkipListSet(Comparator<? super E> comparator) { m = new ConcurrentSkipListMap<E,Object>(comparator); } // Initialize map using ConcurrentSkipListMap // And put all the elements in the set c into the map public ConcurrentSkipListSet(Collection<? extends E> c) { m = new ConcurrentSkipListMap<E,Object>(); addAll(c); } // Initialize map using ConcurrentSkipListMap // And put all the elements in the ordered Set into the map public ConcurrentSkipListSet(SortedSet<E> s) { m = new ConcurrentSkipListMap<E,Object>(s.comparator()); addAll(s); } // Used when returning a child set inside the ConcurrentSkipListSet class ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) { this.m = m; } // Cloning Method public ConcurrentSkipListSet<E> clone() { try { @SuppressWarnings("unchecked") ConcurrentSkipListSet<E> clone = (ConcurrentSkipListSet<E>) super.clone(); clone.setMap(new ConcurrentSkipListMap<E,Object>(m)); return clone; } catch (CloneNotSupportedException e) { throw new InternalError(); } } /* ---------------- Set operations -------------- */ // Returns the number of elements public int size() { return m.size(); } // Check if empty public boolean isEmpty() { return m.isEmpty(); } // Check to see if an element is included public boolean contains(Object o) { return m.containsKey(o); } // Add an element // Call map's putIfAbsent() method public boolean add(E e) { return m.putIfAbsent(e, Boolean.TRUE) == null; } // Remove an element public boolean remove(Object o) { return m.remove(o, Boolean.TRUE); } // Empty all elements public void clear() { m.clear(); } // iterator public Iterator<E> iterator() { return m.navigableKeySet().iterator(); } // Descending iterator public Iterator<E> descendingIterator() { return m.descendingKeySet().iterator(); } /* ---------------- AbstractSet Overrides -------------- */ // Comparative equality and other methods 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 { // Here's a comparison through two two layers of for loops // There is a lot of room for optimizing, refer to the egg in the CopyOnWriteArraySet article above return containsAll(c) && c.containsAll(this); } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } } // Remove all elements from set 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 -------------- */ // Maximum element less than e public E lower(E e) { return m.lowerKey(e); } // The largest element less than or equal to e public E floor(E e) { return m.floorKey(e); } // The smallest element greater than or equal to e public E ceiling(E e) { return m.ceilingKey(e); } // Minimum element greater than e public E higher(E e) { return m.higherKey(e); } // Pop up the smallest element public E pollFirst() { Map.Entry<E,Object> e = m.pollFirstEntry(); return (e == null) ? null : e.getKey(); } // Pop up the biggest element public E pollLast() { Map.Entry<E,Object> e = m.pollLastEntry(); return (e == null) ? null : e.getKey(); } /* ---------------- SortedSet operations -------------- */ // Comparator public Comparator<? super E> comparator() { return m.comparator(); } // The smallest element public E first() { return m.firstKey(); } // The largest element public E last() { return m.lastKey(); } // Take a child set between two elements public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new ConcurrentSkipListSet<E> (m.subMap(fromElement, fromInclusive, toElement, toInclusive)); } // Header set public NavigableSet<E> headSet(E toElement, boolean inclusive) { return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive)); } // Tail set public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive)); } // Sub set, containing from, not to public NavigableSet<E> subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } // Header Sub set, does not contain to public NavigableSet<E> headSet(E toElement) { return headSet(toElement, false); } // Tail set, containing from public NavigableSet<E> tailSet(E fromElement) { return tailSet(fromElement, true); } // Descending set public NavigableSet<E> descendingSet() { return new ConcurrentSkipListSet<E>(m.descendingMap()); } // A divisible iterator @SuppressWarnings("unchecked") public Spliterator<E> spliterator() { if (m instanceof ConcurrentSkipListMap) return ((ConcurrentSkipListMap<E,?>)m).keySpliterator(); else return (Spliterator<E>)((ConcurrentSkipListMap.SubMap<E,?>)m).keyIterator(); } // Atomic update map, use for clone method private void setMap(ConcurrentNavigableMap<E,Object> map) { UNSAFE.putObjectVolatile(this, mapOffset, map); } // Atomic operations related content 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); } } }
As you can see, ConcurrentSkipListSet s are basically implemented using ConcurrentSkipListMap. Although the sub set is partially implemented using internal classes in ConcurrentSkipListMap, these internal classes are also related to ConcurrentSkipListMap and return part of the ConcurrentSkipListMap data.
In addition, the equals() method here is fairly pervasive and has a lot of room for optimization, so the author knows that few people call the equals() method.
summary
(1) ConcurrentSkipListSet is implemented using ConcurrentNavigableMap at the bottom;
(2) ConcurrentSkipListSet is ordered, based on the natural ordering of elements or the order determined by the comparator;
(3) ConcurrentSkipListSet is thread-safe;
Eggs
Set Summary:
Set | Orderliness | Thread Security | Bottom level implementation | Key interfaces | Characteristic |
---|---|---|---|---|---|
HashSet | nothing | no | HashMap | nothing | simple |
LinkedHashSet | Yes | no | LinkedHashMap | nothing | Insertion order |
TreeSet | Yes | no | NavigableMap | NavigableSet | Natural order |
CopyOnWriteArraySet | Yes | yes | CopyOnWriteArrayList | nothing | Insert order, read-write separation |
ConcurrentSkipListSet | Yes | yes | ConcurrentNavigableMap | NavigableSet | Natural order |
From this we can find some rules:
(1) All Sets except HashSet are ordered;
(2) The implementation of NavigableSet or SortedSet interfaces is in natural order;
(3) Sets implemented using a Set of concurrent security are also concurrent security;
(4) Although not all TreeSet s are implemented using TreeMap, they are all related to TreeMap (TreeMap is combined in a submap of TreeMap);
(5) ConcurrentSkipListSet, although not all are implemented using ConcurrentSkipListMap, is actually related to ConcurrentSkipListMap (ConcurrentSkipListMap is a combination of ConcurrentSkipListMap in the submaps of ConcurrentSkipListeMap);
Welcome to pay attention to my public number "Tong Gong Read Source". Check out more articles about source series and enjoy the sea of source code with Tong Gong.