ConcurrentSkipListSet Source Analysis for java Collections - Set Summary

Keywords: Java less

ConcurrentSkipListSet Source Analysis for java Collections - Set Summary
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

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 Ordered Thread Security Bottom Level Implements Key Interface Features
HashSet No HashMap No Simple
Whether LinkedHashSet has LinkedHashMap without insertion order
Does TreeSet have NavigableMap NavigableSet natural order
CopyOnWriteArraySet has CopyOnWriteArrayList without insertion order, read-write separation
ConcurrentSkipListSet has a natural order of ConcurrentNavigableMap NavigableSet
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);
Original Address https://www.cnblogs.com/tong-yuan/p/ConcurrentSkipListSet.html

Posted by DwarV on Thu, 09 May 2019 11:08:38 -0700