Concurrent Skip List Map : Customized Map « Collections Data Structure « Java






Concurrent Skip List Map

    

/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/licenses/publicdomain
 */

import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * A {@link SortedMap} extended with navigation methods returning the closest
 * matches for given search targets. Methods <tt>lowerEntry</tt>,
 * <tt>floorEntry</tt>, <tt>ceilingEntry</tt>, and <tt>higherEntry</tt>
 * return <tt>Map.Entry</tt> objects associated with keys respectively less
 * than, less than or equal, greater than or equal, and greater than a given
 * key, returning <tt>null</tt> if there is no such key. Similarly, methods
 * <tt>lowerKey</tt>, <tt>floorKey</tt>, <tt>ceilingKey</tt>, and
 * <tt>higherKey</tt> return only the associated keys. All of these methods
 * are designed for locating, not traversing entries.
 * 
 * <p>
 * A <tt>NavigableMap</tt> may be viewed and traversed in either ascending or
 * descending key order. The <tt>Map</tt> methods <tt>keySet</tt> and
 * <tt>entrySet</tt> return ascending views, and the additional methods
 * <tt>descendingKeySet</tt> and <tt>descendingEntrySet</tt> return
 * descending views. The performance of ascending traversals is likely to be
 * faster than descending traversals. Notice that it is possible to perform
 * subrannge traversals in either direction using <tt>SubMap</tt>.
 * 
 * <p>
 * This interface additionally defines methods <tt>firstEntry</tt>,
 * <tt>pollFirstEntry</tt>, <tt>lastEntry</tt>, and <tt>pollLastEntry</tt>
 * that return and/or remove the least and greatest mappings, if any exist, else
 * returning <tt>null</tt>.
 * 
 * <p>
 * Implementations of entry-returning methods are expected to return
 * <tt>Map.Entry</tt> pairs representing snapshots of mappings at the time
 * they were produced, and thus generally do <em>not</em> support the optional
 * <tt>Entry.setValue</tt> method. Note however that it is possible to change
 * mappings in the associated map using method <tt>put</tt>.
 * 
 * @author Doug Lea
 * @param <K>
 *          the type of keys maintained by this map
 * @param <V>
 *          the type of mapped values
 */
interface NavigableMap<K, V> extends SortedMap<K, V> {
  /**
   * Returns a key-value mapping associated with the least key greater than or
   * equal to the given key, or <tt>null</tt> if there is no such entry.
   * 
   * @param key
   *          the key.
   * @return an Entry associated with ceiling of given key, or <tt>null</tt>
   *         if there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public Map.Entry<K, V> ceilingEntry(K key);

  /**
   * Returns least key greater than or equal to the given key, or <tt>null</tt>
   * if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the ceiling key, or <tt>null</tt> if there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public K ceilingKey(K key);

  /**
   * Returns a key-value mapping associated with the greatest key strictly less
   * than the given key, or <tt>null</tt> if there is no such entry.
   * 
   * @param key
   *          the key.
   * @return an Entry with greatest key less than the given key, or
   *         <tt>null</tt> if there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public Map.Entry<K, V> lowerEntry(K key);

  /**
   * Returns the greatest key strictly less than the given key, or <tt>null</tt>
   * if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the greatest key less than the given key, or <tt>null</tt> if
   *         there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public K lowerKey(K key);

  /**
   * Returns a key-value mapping associated with the greatest key less than or
   * equal to the given key, or <tt>null</tt> if there is no such entry.
   * 
   * @param key
   *          the key.
   * @return an Entry associated with floor of given key, or <tt>null</tt> if
   *         there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public Map.Entry<K, V> floorEntry(K key);

  /**
   * Returns the greatest key less than or equal to the given key, or
   * <tt>null</tt> if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the floor of given key, or <tt>null</tt> if there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public K floorKey(K key);

  /**
   * Returns a key-value mapping associated with the least key strictly greater
   * than the given key, or <tt>null</tt> if there is no such entry.
   * 
   * @param key
   *          the key.
   * @return an Entry with least key greater than the given key, or
   *         <tt>null</tt> if there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public Map.Entry<K, V> higherEntry(K key);

  /**
   * Returns the least key strictly greater than the given key, or <tt>null</tt>
   * if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the least key greater than the given key, or <tt>null</tt> if
   *         there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt> and this map does not support
   *           <tt>null</tt> keys.
   */
  public K higherKey(K key);

  /**
   * Returns a key-value mapping associated with the least key in this map, or
   * <tt>null</tt> if the map is empty.
   * 
   * @return an Entry with least key, or <tt>null</tt> if the map is empty.
   */
  public Map.Entry<K, V> firstEntry();

  /**
   * Returns a key-value mapping associated with the greatest key in this map,
   * or <tt>null</tt> if the map is empty.
   * 
   * @return an Entry with greatest key, or <tt>null</tt> if the map is empty.
   */
  public Map.Entry<K, V> lastEntry();

  /**
   * Removes and returns a key-value mapping associated with the least key in
   * this map, or <tt>null</tt> if the map is empty.
   * 
   * @return the removed first entry of this map, or <tt>null</tt> if the map
   *         is empty.
   */
  public Map.Entry<K, V> pollFirstEntry();

  /**
   * Removes and returns a key-value mapping associated with the greatest key in
   * this map, or <tt>null</tt> if the map is empty.
   * 
   * @return the removed last entry of this map, or <tt>null</tt> if the map
   *         is empty.
   */
  public Map.Entry<K, V> pollLastEntry();

  /**
   * Returns a set view of the keys contained in this map, in descending key
   * order. The set is backed by the map, so changes to the map are reflected in
   * the set, and vice-versa. If the map is modified while an iteration over the
   * set is in progress (except through the iterator's own <tt>remove</tt>
   * operation), the results of the iteration are undefined. The set supports
   * element removal, which removes the corresponding mapping from the map, via
   * the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
   * <tt>removeAll</tt> <tt>retainAll</tt>, and <tt>clear</tt>
   * operations. It does not support the add or <tt>addAll</tt> operations.
   * 
   * @return a set view of the keys contained in this map.
   */
  Set<K> descendingKeySet();

  /**
   * Returns a set view of the mappings contained in this map, in descending key
   * order. Each element in the returned set is a <tt>Map.Entry</tt>. The set
   * is backed by the map, so changes to the map are reflected in the set, and
   * vice-versa. If the map is modified while an iteration over the set is in
   * progress (except through the iterator's own <tt>remove</tt> operation, or
   * through the <tt>setValue</tt> operation on a map entry returned by the
   * iterator) the results of the iteration are undefined. The set supports
   * element removal, which removes the corresponding mapping from the map, via
   * the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
   * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support
   * the <tt>add</tt> or <tt>addAll</tt> operations.
   * 
   * @return a set view of the mappings contained in this map.
   */
  Set<Map.Entry<K, V>> descendingEntrySet();

  /**
   * Returns a view of the portion of this map whose keys range from
   * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive. (If
   * <tt>fromKey</tt> and <tt>toKey</tt> are equal, the returned sorted map
   * is empty.) The returned sorted map is backed by this map, so changes in the
   * returned sorted map are reflected in this map, and vice-versa.
   * 
   * @param fromKey
   *          low endpoint (inclusive) of the subMap.
   * @param toKey
   *          high endpoint (exclusive) of the subMap.
   * 
   * @return a view of the portion of this map whose keys range from
   *         <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive.
   * 
   * @throws ClassCastException
   *           if <tt>fromKey</tt> and <tt>toKey</tt> cannot be compared to
   *           one another using this map's comparator (or, if the map has no
   *           comparator, using natural ordering).
   * @throws IllegalArgumentException
   *           if <tt>fromKey</tt> is greater than <tt>toKey</tt>.
   * @throws NullPointerException
   *           if <tt>fromKey</tt> or <tt>toKey</tt> is <tt>null</tt> and
   *           this map does not support <tt>null</tt> keys.
   */
  public NavigableMap<K, V> subMap(K fromKey, K toKey);

  /**
   * Returns a view of the portion of this map whose keys are strictly less than
   * <tt>toKey</tt>. The returned sorted map is backed by this map, so
   * changes in the returned sorted map are reflected in this map, and
   * vice-versa.
   * 
   * @param toKey
   *          high endpoint (exclusive) of the headMap.
   * @return a view of the portion of this map whose keys are strictly less than
   *         <tt>toKey</tt>.
   * 
   * @throws ClassCastException
   *           if <tt>toKey</tt> is not compatible with this map's comparator
   *           (or, if the map has no comparator, if <tt>toKey</tt> does not
   *           implement <tt>Comparable</tt>).
   * @throws NullPointerException
   *           if <tt>toKey</tt> is <tt>null</tt> and this map does not
   *           support <tt>null</tt> keys.
   */
  public NavigableMap<K, V> headMap(K toKey);

  /**
   * Returns a view of the portion of this map whose keys are greater than or
   * equal to <tt>fromKey</tt>. The returned sorted map is backed by this
   * map, so changes in the returned sorted map are reflected in this map, and
   * vice-versa.
   * 
   * @param fromKey
   *          low endpoint (inclusive) of the tailMap.
   * @return a view of the portion of this map whose keys are greater than or
   *         equal to <tt>fromKey</tt>.
   * @throws ClassCastException
   *           if <tt>fromKey</tt> is not compatible with this map's
   *           comparator (or, if the map has no comparator, if <tt>fromKey</tt>
   *           does not implement <tt>Comparable</tt>).
   * @throws NullPointerException
   *           if <tt>fromKey</tt> is <tt>null</tt> and this map does not
   *           support <tt>null</tt> keys.
   */
  public NavigableMap<K, V> tailMap(K fromKey);
}

/**
 * A {@link ConcurrentMap} supporting {@link NavigableMap} operations.
 * 
 * @author Doug Lea
 * @param <K>
 *          the type of keys maintained by this map
 * @param <V>
 *          the type of mapped values
 */
interface ConcurrentNavigableMap<K, V> extends ConcurrentMap<K, V>, NavigableMap<K, V> {
  /**
   * Returns a view of the portion of this map whose keys range from
   * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive. (If
   * <tt>fromKey</tt> and <tt>toKey</tt> are equal, the returned sorted map
   * is empty.) The returned sorted map is backed by this map, so changes in the
   * returned sorted map are reflected in this map, and vice-versa.
   * 
   * @param fromKey
   *          low endpoint (inclusive) of the subMap.
   * @param toKey
   *          high endpoint (exclusive) of the subMap.
   * 
   * @return a view of the portion of this map whose keys range from
   *         <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive.
   * 
   * @throws ClassCastException
   *           if <tt>fromKey</tt> and <tt>toKey</tt> cannot be compared to
   *           one another using this map's comparator (or, if the map has no
   *           comparator, using natural ordering).
   * @throws IllegalArgumentException
   *           if <tt>fromKey</tt> is greater than <tt>toKey</tt>.
   * @throws NullPointerException
   *           if <tt>fromKey</tt> or <tt>toKey</tt> is <tt>null</tt> and
   *           this map does not support <tt>null</tt> keys.
   */
  public ConcurrentNavigableMap<K, V> subMap(K fromKey, K toKey);

  /**
   * Returns a view of the portion of this map whose keys are strictly less than
   * <tt>toKey</tt>. The returned sorted map is backed by this map, so
   * changes in the returned sorted map are reflected in this map, and
   * vice-versa.
   * 
   * @param toKey
   *          high endpoint (exclusive) of the headMap.
   * @return a view of the portion of this map whose keys are strictly less than
   *         <tt>toKey</tt>.
   * 
   * @throws ClassCastException
   *           if <tt>toKey</tt> is not compatible with this map's comparator
   *           (or, if the map has no comparator, if <tt>toKey</tt> does not
   *           implement <tt>Comparable</tt>).
   * @throws NullPointerException
   *           if <tt>toKey</tt> is <tt>null</tt> and this map does not
   *           support <tt>null</tt> keys.
   */
  public ConcurrentNavigableMap<K, V> headMap(K toKey);

  /**
   * Returns a view of the portion of this map whose keys are greater than or
   * equal to <tt>fromKey</tt>. The returned sorted map is backed by this
   * map, so changes in the returned sorted map are reflected in this map, and
   * vice-versa.
   * 
   * @param fromKey
   *          low endpoint (inclusive) of the tailMap.
   * @return a view of the portion of this map whose keys are greater than or
   *         equal to <tt>fromKey</tt>.
   * @throws ClassCastException
   *           if <tt>fromKey</tt> is not compatible with this map's
   *           comparator (or, if the map has no comparator, if <tt>fromKey</tt>
   *           does not implement <tt>Comparable</tt>).
   * @throws NullPointerException
   *           if <tt>fromKey</tt> is <tt>null</tt> and this map does not
   *           support <tt>null</tt> keys.
   */
  public ConcurrentNavigableMap<K, V> tailMap(K fromKey);
}

/**
 * A scalable {@link ConcurrentNavigableMap} implementation. This class
 * maintains a map in ascending key order, sorted according to the <i>natural
 * order</i> for the key's class (see {@link Comparable}), or by the
 * {@link Comparator} provided at creation time, depending on which constructor
 * is used.
 * 
 * <p>
 * This class implements a concurrent variant of <a
 * href="http://www.cs.umd.edu/~pugh/">SkipLists</a> providing expected average
 * <i>log(n)</i> time cost for the <tt>containsKey</tt>, <tt>get</tt>,
 * <tt>put</tt> and <tt>remove</tt> operations and their variants.
 * Insertion, removal, update, and access operations safely execute concurrently
 * by multiple threads. Iterators are <i>weakly consistent</i>, returning
 * elements reflecting the state of the map at some point at or since the
 * creation of the iterator. They do <em>not</em> throw {@link
 * ConcurrentModificationException}, and may proceed concurrently with other
 * operations. Ascending key ordered views and their iterators are faster than
 * descending ones.
 * 
 * <p>
 * All <tt>Map.Entry</tt> pairs returned by methods in this class and its
 * views represent snapshots of mappings at the time they were produced. They do
 * <em>not</em> support the <tt>Entry.setValue</tt> method. (Note however
 * that it is possible to change mappings in the associated map using
 * <tt>put</tt>, <tt>putIfAbsent</tt>, or <tt>replace</tt>, depending
 * on exactly which effect you need.)
 * 
 * <p>
 * Beware that, unlike in most collections, the <tt>size</tt> method is
 * <em>not</em> a constant-time operation. Because of the asynchronous nature
 * of these maps, determining the current number of elements requires a
 * traversal of the elements. Additionally, the bulk operations <tt>putAll</tt>,
 * <tt>equals</tt>, and <tt>clear</tt> are <em>not</em> guaranteed to be
 * performed atomically. For example, an iterator operating concurrently with a
 * <tt>putAll</tt> operation might view only some of the added elements.
 * 
 * <p>
 * This class and its views and iterators implement all of the <em>optional</em>
 * methods of the {@link Map} and {@link Iterator} interfaces. Like most other
 * concurrent collections, this class does not permit the use of <tt>null</tt>
 * keys or values because some null return values cannot be reliably
 * distinguished from the absence of elements.
 * 
 * @author Doug Lea
 * @param <K>
 *          the type of keys maintained by this map
 * @param <V>
 *          the type of mapped values
 */
public class ConcurrentSkipListMap<K, V> extends AbstractMap<K, V> implements
    ConcurrentNavigableMap<K, V>, Cloneable, java.io.Serializable {
  /*
   * This class implements a tree-like two-dimensionally linked skip list in
   * which the index levels are represented in separate nodes from the base
   * nodes holding data. There are two reasons for taking this approach instead
   * of the usual array-based structure: 1) Array based implementations seem to
   * encounter more complexity and overhead 2) We can use cheaper algorithms for
   * the heavily-traversed index lists than can be used for the base lists.
   * Here's a picture of some of the basics for a possible list with 2 levels of
   * index:
   * 
   * Head nodes Index nodes +-+ right +-+ +-+ |2|---------------->|
   * |--------------------->| |->null +-+ +-+ +-+ | down | | v v v +-+ +-+ +-+
   * +-+ +-+ +-+ |1|----------->| |->| |------>| |----------->| |------>|
   * |->null +-+ +-+ +-+ +-+ +-+ +-+ v | | | | | Nodes next v v v v v +-+ +-+
   * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
   * |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null +-+ +-+ +-+
   * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
   * 
   * The base lists use a variant of the HM linked ordered set algorithm. See
   * Tim Harris, "A pragmatic implementation of non-blocking linked lists"
   * http://www.cl.cam.ac.uk/~tlh20/publications.html and Maged Michael "High
   * Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
   * http://www.research.ibm.com/people/m/michael/pubs.htm. The basic idea in
   * these lists is to mark the "next" pointers of deleted nodes when deleting
   * to avoid conflicts with concurrent insertions, and when traversing to keep
   * track of triples (predecessor, node, successor) in order to detect when and
   * how to unlink these deleted nodes.
   * 
   * Rather than using mark-bits to mark list deletions (which can be slow and
   * space-intensive using AtomicMarkedReference), nodes use direct CAS'able
   * next pointers. On deletion, instead of marking a pointer, they splice in
   * another node that can be thought of as standing for a marked pointer
   * (indicating this by using otherwise impossible field values). Using plain
   * nodes acts roughly like "boxed" implementations of marked pointers, but
   * uses new nodes only when nodes are deleted, not for every link. This
   * requires less space and supports faster traversal. Even if marked
   * references were better supported by JVMs, traversal using this technique
   * might still be faster because any search need only read ahead one more node
   * than otherwise required (to check for trailing marker) rather than
   * unmasking mark bits or whatever on each read.
   * 
   * This approach maintains the essential property needed in the HM algorithm
   * of changing the next-pointer of a deleted node so that any other CAS of it
   * will fail, but implements the idea by changing the pointer to point to a
   * different node, not by marking it. While it would be possible to further
   * squeeze space by defining marker nodes not to have key/value fields, it
   * isn't worth the extra type-testing overhead. The deletion markers are
   * rarely encountered during traversal and are normally quickly garbage
   * collected. (Note that this technique would not work well in systems without
   * garbage collection.)
   * 
   * In addition to using deletion markers, the lists also use nullness of value
   * fields to indicate deletion, in a style similar to typical lazy-deletion
   * schemes. If a node's value is null, then it is considered logically deleted
   * and ignored even though it is still reachable. This maintains proper
   * control of concurrent replace vs delete operations -- an attempted replace
   * must fail if a delete beat it by nulling field, and a delete must return
   * the last non-null value held in the field. (Note: Null, rather than some
   * special marker, is used for value fields here because it just so happens to
   * mesh with the Map API requirement that method get returns null if there is
   * no mapping, which allows nodes to remain concurrently readable even when
   * deleted. Using any other marker value here would be messy at best.)
   * 
   * Here's the sequence of events for a deletion of node n with predecessor b
   * and successor f, initially:
   * 
   * +------+ +------+ +------+ ... | b |------>| n |----->| f | ... +------+
   * +------+ +------+
   * 
   * 1. CAS n's value field from non-null to null. From this point on, no public
   * operations encountering the node consider this mapping to exist. However,
   * other ongoing insertions and deletions might still modify n's next pointer.
   * 
   * 2. CAS n's next pointer to point to a new marker node. From this point on,
   * no other nodes can be appended to n. which avoids deletion errors in
   * CAS-based linked lists.
   * 
   * +------+ +------+ +------+ +------+ ... | b |------>| n
   * |----->|marker|------>| f | ... +------+ +------+ +------+ +------+
   * 
   * 3. CAS b's next pointer over both n and its marker. From this point on, no
   * new traversals will encounter n, and it can eventually be GCed. +------+
   * +------+ ... | b |----------------------------------->| f | ... +------+
   * +------+
   * 
   * A failure at step 1 leads to simple retry due to a lost race with another
   * operation. Steps 2-3 can fail because some other thread noticed during a
   * traversal a node with null value and helped out by marking and/or
   * unlinking. This helping-out ensures that no thread can become stuck waiting
   * for progress of the deleting thread. The use of marker nodes slightly
   * complicates helping-out code because traversals must track consistent reads
   * of up to four nodes (b, n, marker, f), not just (b, n, f), although the
   * next field of a marker is immutable, and once a next field is CAS'ed to
   * point to a marker, it never again changes, so this requires less care.
   * 
   * Skip lists add indexing to this scheme, so that the base-level traversals
   * start close to the locations being found, inserted or deleted -- usually
   * base level traversals only traverse a few nodes. This doesn't change the
   * basic algorithm except for the need to make sure base traversals start at
   * predecessors (here, b) that are not (structurally) deleted, otherwise
   * retrying after processing the deletion.
   * 
   * Index levels are maintained as lists with volatile next fields, using CAS
   * to link and unlink. Races are allowed in index-list operations that can
   * (rarely) fail to link in a new index node or delete one. (We can't do this
   * of course for data nodes.) However, even when this happens, the index lists
   * remain sorted, so correctly serve as indices. This can impact performance,
   * but since skip lists are probabilistic anyway, the net result is that under
   * contention, the effective "p" value may be lower than its nominal value.
   * And race windows are kept small enough that in practice these failures are
   * rare, even under a lot of contention.
   * 
   * The fact that retries (for both base and index lists) are relatively cheap
   * due to indexing allows some minor simplifications of retry logic. Traversal
   * restarts are performed after most "helping-out" CASes. This isn't always
   * strictly necessary, but the implicit backoffs tend to help reduce other
   * downstream failed CAS's enough to outweigh restart cost. This worsens the
   * worst case, but seems to improve even highly contended cases.
   * 
   * Unlike most skip-list implementations, index insertion and deletion here
   * require a separate traversal pass occuring after the base-level action, to
   * add or remove index nodes. This adds to single-threaded overhead, but
   * improves contended multithreaded performance by narrowing interference
   * windows, and allows deletion to ensure that all index nodes will be made
   * unreachable upon return from a public remove operation, thus avoiding
   * unwanted garbage retention. This is more important here than in some other
   * data structures because we cannot null out node fields referencing user
   * keys since they might still be read by other ongoing traversals.
   * 
   * Indexing uses skip list parameters that maintain good search performance
   * while using sparser-than-usual indices: The hardwired parameters k=1, p=0.5
   * (see method randomLevel) mean that about one-quarter of the nodes have
   * indices. Of those that do, half have one level, a quarter have two, and so
   * on (see Pugh's Skip List Cookbook, sec 3.4). The expected total space
   * requirement for a map is slightly less than for the current implementation
   * of java.util.TreeMap.
   * 
   * Changing the level of the index (i.e, the height of the tree-like
   * structure) also uses CAS. The head index has initial level/height of one.
   * Creation of an index with height greater than the current level adds a
   * level to the head index by CAS'ing on a new top-most head. To maintain good
   * performance after a lot of removals, deletion methods heuristically try to
   * reduce the height if the topmost levels appear to be empty. This may
   * encounter races in which it possible (but rare) to reduce and "lose" a
   * level just as it is about to contain an index (that will then never be
   * encountered). This does no structural harm, and in practice appears to be a
   * better option than allowing unrestrained growth of levels.
   * 
   * The code for all this is more verbose than you'd like. Most operations
   * entail locating an element (or position to insert an element). The code to
   * do this can't be nicely factored out because subsequent uses require a
   * snapshot of predecessor and/or successor and/or value fields which can't be
   * returned all at once, at least not without creating yet another object to
   * hold them -- creating such little objects is an especially bad idea for
   * basic internal search operations because it adds to GC overhead. (This is
   * one of the few times I've wished Java had macros.) Instead, some traversal
   * code is interleaved within insertion and removal operations. The control
   * logic to handle all the retry conditions is sometimes twisty. Most search
   * is broken into 2 parts. findPredecessor() searches index nodes only,
   * returning a base-level predecessor of the key. findNode() finishes out the
   * base-level search. Even with this factoring, there is a fair amount of
   * near-duplication of code to handle variants.
   * 
   * For explanation of algorithms sharing at least a couple of features with
   * this one, see Mikhail Fomitchev's thesis
   * (http://www.cs.yorku.ca/~mikhail/), Keir Fraser's thesis
   * (http://www.cl.cam.ac.uk/users/kaf24/), and Hakan Sundell's thesis
   * (http://www.cs.chalmers.se/~phs/).
   * 
   * Given the use of tree-like index nodes, you might wonder why this doesn't
   * use some kind of search tree instead, which would support somewhat faster
   * search operations. The reason is that there are no known efficient
   * lock-free insertion and deletion algorithms for search trees. The
   * immutability of the "down" links of index nodes (as opposed to mutable
   * "left" fields in true trees) makes this tractable using only CAS
   * operations.
   * 
   * Notation guide for local variables Node: b, n, f for predecessor, node,
   * successor Index: q, r, d for index node, right, down. t for another index
   * node Head: h Levels: j Keys: k, key Values: v, value Comparisons: c
   */

  private static final long serialVersionUID = -8627078645895051609L;

  /**
   * Special value used to identify base-level header
   */
  private static final Object BASE_HEADER = new Object();

  /**
   * The topmost head index of the skiplist.
   */
  private transient volatile HeadIndex<K, V> head;

  /**
   * The Comparator used to maintain order in this Map, or null if using natural
   * order.
   * 
   * @serial
   */
  private final Comparator<? super K> comparator;

  /**
   * Seed for simple random number generator. Not volatile since it doesn't
   * matter too much if different threads don't see updates.
   */
  private transient int randomSeed;

  /** Lazily initialized key set */
  private transient KeySet keySet;

  /** Lazily initialized entry set */
  private transient EntrySet entrySet;

  /** Lazily initialized values collection */
  private transient Values values;

  /** Lazily initialized descending key set */
  private transient DescendingKeySet descendingKeySet;

  /** Lazily initialized descending entry set */
  private transient DescendingEntrySet descendingEntrySet;

  /**
   * Initialize or reset state. Needed by constructors, clone, clear,
   * readObject. and ConcurrentSkipListSet.clone. (Note that comparator must be
   * separately initialized.)
   */
  final void initialize() {
    keySet = null;
    entrySet = null;
    values = null;
    descendingEntrySet = null;
    descendingKeySet = null;
    randomSeed = (int) System.nanoTime();
    head = new HeadIndex<K, V>(new Node<K, V>(null, BASE_HEADER, null), null, null, 1);
  }

  /** Updater for casHead */
  private static final AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex> headUpdater = AtomicReferenceFieldUpdater
      .newUpdater(ConcurrentSkipListMap.class, HeadIndex.class, "head");

  /**
   * compareAndSet head node
   */
  private boolean casHead(HeadIndex<K, V> cmp, HeadIndex<K, V> val) {
    return headUpdater.compareAndSet(this, cmp, val);
  }

  /* ---------------- Nodes -------------- */

  /**
   * Nodes hold keys and values, and are singly linked in sorted order, possibly
   * with some intervening marker nodes. The list is headed by a dummy node
   * accessible as head.node. The value field is declared only as Object because
   * it takes special non-V values for marker and header nodes.
   */
  static final class Node<K, V> {
    final K key;

    volatile Object value;

    volatile Node<K, V> next;

    /**
     * Creates a new regular node.
     */
    Node(K key, Object value, Node<K, V> next) {
      this.key = key;
      this.value = value;
      this.next = next;
    }

    /**
     * Creates a new marker node. A marker is distinguished by having its value
     * field point to itself. Marker nodes also have null keys, a fact that is
     * exploited in a few places, but this doesn't distinguish markers from the
     * base-level header node (head.node), which also has a null key.
     */
    Node(Node<K, V> next) {
      this.key = null;
      this.value = this;
      this.next = next;
    }

    /** Updater for casNext */
    static final AtomicReferenceFieldUpdater<Node, Node> nextUpdater = AtomicReferenceFieldUpdater
        .newUpdater(Node.class, Node.class, "next");

    /** Updater for casValue */
    static final AtomicReferenceFieldUpdater<Node, Object> valueUpdater = AtomicReferenceFieldUpdater
        .newUpdater(Node.class, Object.class, "value");

    /**
     * compareAndSet value field
     */
    boolean casValue(Object cmp, Object val) {
      return valueUpdater.compareAndSet(this, cmp, val);
    }

    /**
     * compareAndSet next field
     */
    boolean casNext(Node<K, V> cmp, Node<K, V> val) {
      return nextUpdater.compareAndSet(this, cmp, val);
    }

    /**
     * Return true if this node is a marker. This method isn't actually called
     * in an any current code checking for markers because callers will have
     * already read value field and need to use that read (not another done
     * here) and so directly test if value points to node.
     * 
     * @param n
     *          a possibly null reference to a node
     * @return true if this node is a marker node
     */
    boolean isMarker() {
      return value == this;
    }

    /**
     * Return true if this node is the header of base-level list.
     * 
     * @return true if this node is header node
     */
    boolean isBaseHeader() {
      return value == BASE_HEADER;
    }

    /**
     * Tries to append a deletion marker to this node.
     * 
     * @param f
     *          the assumed current successor of this node
     * @return true if successful
     */
    boolean appendMarker(Node<K, V> f) {
      return casNext(f, new Node<K, V>(f));
    }

    /**
     * Helps out a deletion by appending marker or unlinking from predecessor.
     * This is called during traversals when value field seen to be null.
     * 
     * @param b
     *          predecessor
     * @param f
     *          successor
     */
    void helpDelete(Node<K, V> b, Node<K, V> f) {
      /*
       * Rechecking links and then doing only one of the help-out stages per
       * call tends to minimize CAS interference among helping threads.
       */
      if (f == next && this == b.next) {
        if (f == null || f.value != f) // not already marked
          appendMarker(f);
        else
          b.casNext(this, f.next);
      }
    }

    /**
     * Return value if this node contains a valid key-value pair, else null.
     * 
     * @return this node's value if it isn't a marker or header or is deleted,
     *         else null.
     */
    V getValidValue() {
      Object v = value;
      if (v == this || v == BASE_HEADER)
        return null;
      return (V) v;
    }

    /**
     * Create and return a new SnapshotEntry holding current mapping if this
     * node holds a valid value, else null
     * 
     * @return new entry or null
     */
    SnapshotEntry<K, V> createSnapshot() {
      V v = getValidValue();
      if (v == null)
        return null;
      return new SnapshotEntry(key, v);
    }
  }

  /* ---------------- Indexing -------------- */

  /**
   * Index nodes represent the levels of the skip list. To improve search
   * performance, keys of the underlying nodes are cached. Note that even though
   * both Nodes and Indexes have forward-pointing fields, they have different
   * types and are handled in different ways, that can't nicely be captured by
   * placing field in a shared abstract class.
   */
  static class Index<K, V> {
    final K key;

    final Node<K, V> node;

    final Index<K, V> down;

    volatile Index<K, V> right;

    /**
     * Creates index node with given values
     */
    Index(Node<K, V> node, Index<K, V> down, Index<K, V> right) {
      this.node = node;
      this.key = node.key;
      this.down = down;
      this.right = right;
    }

    /** Updater for casRight */
    static final AtomicReferenceFieldUpdater<Index, Index> rightUpdater = AtomicReferenceFieldUpdater
        .newUpdater(Index.class, Index.class, "right");

    /**
     * compareAndSet right field
     */
    final boolean casRight(Index<K, V> cmp, Index<K, V> val) {
      return rightUpdater.compareAndSet(this, cmp, val);
    }

    /**
     * Returns true if the node this indexes has been deleted.
     * 
     * @return true if indexed node is known to be deleted
     */
    final boolean indexesDeletedNode() {
      return node.value == null;
    }

    /**
     * Tries to CAS newSucc as successor. To minimize races with unlink that may
     * lose this index node, if the node being indexed is known to be deleted,
     * it doesn't try to link in.
     * 
     * @param succ
     *          the expected current successor
     * @param newSucc
     *          the new successor
     * @return true if successful
     */
    final boolean link(Index<K, V> succ, Index<K, V> newSucc) {
      Node<K, V> n = node;
      newSucc.right = succ;
      return n.value != null && casRight(succ, newSucc);
    }

    /**
     * Tries to CAS right field to skip over apparent successor succ. Fails
     * (forcing a retraversal by caller) if this node is known to be deleted.
     * 
     * @param succ
     *          the expected current successor
     * @return true if successful
     */
    final boolean unlink(Index<K, V> succ) {
      return !indexesDeletedNode() && casRight(succ, succ.right);
    }
  }

  /* ---------------- Head nodes -------------- */

  /**
   * Nodes heading each level keep track of their level.
   */
  static final class HeadIndex<K, V> extends Index<K, V> {
    final int level;

    HeadIndex(Node<K, V> node, Index<K, V> down, Index<K, V> right, int level) {
      super(node, down, right);
      this.level = level;
    }
  }

  /* ---------------- Map.Entry support -------------- */

  /**
   * An immutable representation of a key-value mapping as it existed at some
   * point in time. This class does <em>not</em> support the
   * <tt>Map.Entry.setValue</tt> method.
   */
  static class SnapshotEntry<K, V> implements Map.Entry<K, V> {
    private final K key;

    private final V value;

    /**
     * Creates a new entry representing the given key and value.
     * 
     * @param key
     *          the key
     * @param value
     *          the value
     */
    SnapshotEntry(K key, V value) {
      this.key = key;
      this.value = value;
    }

    /**
     * Returns the key corresponding to this entry.
     * 
     * @return the key corresponding to this entry.
     */
    public K getKey() {
      return key;
    }

    /**
     * Returns the value corresponding to this entry.
     * 
     * @return the value corresponding to this entry.
     */
    public V getValue() {
      return value;
    }

    /**
     * Always fails, throwing <tt>UnsupportedOperationException</tt>.
     * 
     * @throws UnsupportedOperationException
     *           always.
     */
    public V setValue(V value) {
      throw new UnsupportedOperationException();
    }

    // inherit javadoc
    public boolean equals(Object o) {
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry e = (Map.Entry) o;
      // As mandated by Map.Entry spec:
      return ((key == null ? e.getKey() == null : key.equals(e.getKey())) && (value == null ? e
          .getValue() == null : value.equals(e.getValue())));
    }

    // inherit javadoc
    public int hashCode() {
      // As mandated by Map.Entry spec:
      return ((key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()));
    }

    /**
     * Returns a String consisting of the key followed by an equals sign (<tt>"="</tt>)
     * followed by the associated value.
     * 
     * @return a String representation of this entry.
     */
    public String toString() {
      return getKey() + "=" + getValue();
    }
  }

  /* ---------------- Comparison utilities -------------- */

  /**
   * Represents a key with a comparator as a Comparable.
   * 
   * Because most sorted collections seem to use natural order on Comparables
   * (Strings, Integers, etc), most internal methods are geared to use them.
   * This is generally faster than checking per-comparison whether to use
   * comparator or comparable because it doesn't require a (Comparable) cast for
   * each comparison. (Optimizers can only sometimes remove such redundant
   * checks themselves.) When Comparators are used, ComparableUsingComparators
   * are created so that they act in the same way as natural orderings. This
   * penalizes use of Comparators vs Comparables, which seems like the right
   * tradeoff.
   */
  static final class ComparableUsingComparator<K> implements Comparable<K> {
    final K actualKey;

    final Comparator<? super K> cmp;

    ComparableUsingComparator(K key, Comparator<? super K> cmp) {
      this.actualKey = key;
      this.cmp = cmp;
    }

    public int compareTo(K k2) {
      return cmp.compare(actualKey, k2);
    }
  }

  /**
   * If using comparator, return a ComparableUsingComparator, else cast key as
   * Comparator, which may cause ClassCastException, which is propagated back to
   * caller.
   */
  private Comparable<K> comparable(Object key) throws ClassCastException {
    if (key == null)
      throw new NullPointerException();
    return (comparator != null) ? new ComparableUsingComparator(key, comparator)
        : (Comparable<K>) key;
  }

  /**
   * Compare using comparator or natural ordering. Used when the
   * ComparableUsingComparator approach doesn't apply.
   */
  int compare(K k1, K k2) throws ClassCastException {
    Comparator<? super K> cmp = comparator;
    if (cmp != null)
      return cmp.compare(k1, k2);
    else
      return ((Comparable<K>) k1).compareTo(k2);
  }

  /**
   * Return true if given key greater than or equal to least and strictly less
   * than fence, bypassing either test if least or fence oare null. Needed
   * mainly in submap operations.
   */
  boolean inHalfOpenRange(K key, K least, K fence) {
    if (key == null)
      throw new NullPointerException();
    return ((least == null || compare(key, least) >= 0) && (fence == null || compare(key, fence) < 0));
  }

  /**
   * Return true if given key greater than or equal to least and less or equal
   * to fence. Needed mainly in submap operations.
   */
  boolean inOpenRange(K key, K least, K fence) {
    if (key == null)
      throw new NullPointerException();
    return ((least == null || compare(key, least) >= 0) && (fence == null || compare(key, fence) <= 0));
  }

  /* ---------------- Traversal -------------- */

  /**
   * Return a base-level node with key strictly less than given key, or the
   * base-level header if there is no such node. Also unlinks indexes to deleted
   * nodes found along the way. Callers rely on this side-effect of clearing
   * indices to deleted nodes.
   * 
   * @param key
   *          the key
   * @return a predecessor of key
   */
  private Node<K, V> findPredecessor(Comparable<K> key) {
    for (;;) {
      Index<K, V> q = head;
      for (;;) {
        Index<K, V> d, r;
        if ((r = q.right) != null) {
          if (r.indexesDeletedNode()) {
            if (q.unlink(r))
              continue; // reread r
            else
              break; // restart
          }
          if (key.compareTo(r.key) > 0) {
            q = r;
            continue;
          }
        }
        if ((d = q.down) != null)
          q = d;
        else
          return q.node;
      }
    }
  }

  /**
   * Return node holding key or null if no such, clearing out any deleted nodes
   * seen along the way. Repeatedly traverses at base-level looking for key
   * starting at predecessor returned from findPredecessor, processing
   * base-level deletions as encountered. Some callers rely on this side-effect
   * of clearing deleted nodes.
   * 
   * Restarts occur, at traversal step centered on node n, if:
   * 
   * (1) After reading n's next field, n is no longer assumed predecessor b's
   * current successor, which means that we don't have a consistent 3-node
   * snapshot and so cannot unlink any subsequent deleted nodes encountered.
   * 
   * (2) n's value field is null, indicating n is deleted, in which case we help
   * out an ongoing structural deletion before retrying. Even though there are
   * cases where such unlinking doesn't require restart, they aren't sorted out
   * here because doing so would not usually outweigh cost of restarting.
   * 
   * (3) n is a marker or n's predecessor's value field is null, indicating
   * (among other possibilities) that findPredecessor returned a deleted node.
   * We can't unlink the node because we don't know its predecessor, so rely on
   * another call to findPredecessor to notice and return some earlier
   * predecessor, which it will do. This check is only strictly needed at
   * beginning of loop, (and the b.value check isn't strictly needed at all) but
   * is done each iteration to help avoid contention with other threads by
   * callers that will fail to be able to change links, and so will retry
   * anyway.
   * 
   * The traversal loops in doPut, doRemove, and findNear all include the same
   * three kinds of checks. And specialized versions appear in doRemoveFirst,
   * doRemoveLast, findFirst, and findLast. They can't easily share code because
   * each uses the reads of fields held in locals occurring in the orders they
   * were performed.
   * 
   * @param key
   *          the key
   * @return node holding key, or null if no such.
   */
  private Node<K, V> findNode(Comparable<K> key) {
    for (;;) {
      Node<K, V> b = findPredecessor(key);
      Node<K, V> n = b.next;
      for (;;) {
        if (n == null)
          return null;
        Node<K, V> f = n.next;
        if (n != b.next) // inconsistent read
          break;
        Object v = n.value;
        if (v == null) { // n is deleted
          n.helpDelete(b, f);
          break;
        }
        if (v == n || b.value == null) // b is deleted
          break;
        int c = key.compareTo(n.key);
        if (c < 0)
          return null;
        if (c == 0)
          return n;
        b = n;
        n = f;
      }
    }
  }

  /**
   * Specialized variant of findNode to perform Map.get. Does a weak traversal,
   * not bothering to fix any deleted index nodes, returning early if it happens
   * to see key in index, and passing over any deleted base nodes, falling back
   * to getUsingFindNode only if it would otherwise return value from an ongoing
   * deletion. Also uses "bound" to eliminate need for some comparisons (see
   * Pugh Cookbook). Also folds uses of null checks and node-skipping because
   * markers have null keys.
   * 
   * @param okey
   *          the key
   * @return the value, or null if absent
   */
  private V doGet(Object okey) {
    Comparable<K> key = comparable(okey);
    K bound = null;
    Index<K, V> q = head;
    for (;;) {
      K rk;
      Index<K, V> d, r;
      if ((r = q.right) != null && (rk = r.key) != null && rk != bound) {
        int c = key.compareTo(rk);
        if (c > 0) {
          q = r;
          continue;
        }
        if (c == 0) {
          Object v = r.node.value;
          return (v != null) ? (V) v : getUsingFindNode(key);
        }
        bound = rk;
      }
      if ((d = q.down) != null)
        q = d;
      else {
        for (Node<K, V> n = q.node.next; n != null; n = n.next) {
          K nk = n.key;
          if (nk != null) {
            int c = key.compareTo(nk);
            if (c == 0) {
              Object v = n.value;
              return (v != null) ? (V) v : getUsingFindNode(key);
            }
            if (c < 0)
              return null;
          }
        }
        return null;
      }
    }
  }

  /**
   * Perform map.get via findNode. Used as a backup if doGet encounters an
   * in-progress deletion.
   * 
   * @param key
   *          the key
   * @return the value, or null if absent
   */
  private V getUsingFindNode(Comparable<K> key) {
    /*
     * Loop needed here and elsewhere in case value field goes null just as it
     * is about to be returned, in which case we lost a race with a deletion, so
     * must retry.
     */
    for (;;) {
      Node<K, V> n = findNode(key);
      if (n == null)
        return null;
      Object v = n.value;
      if (v != null)
        return (V) v;
    }
  }

  /* ---------------- Insertion -------------- */

  /**
   * Main insertion method. Adds element if not present, or replaces value if
   * present and onlyIfAbsent is false.
   * 
   * @param kkey
   *          the key
   * @param value
   *          the value that must be associated with key
   * @param onlyIfAbsent
   *          if should not insert if already present
   * @return the old value, or null if newly inserted
   */
  private V doPut(K kkey, V value, boolean onlyIfAbsent) {
    Comparable<K> key = comparable(kkey);
    for (;;) {
      Node<K, V> b = findPredecessor(key);
      Node<K, V> n = b.next;
      for (;;) {
        if (n != null) {
          Node<K, V> f = n.next;
          if (n != b.next) // inconsistent read
            break;
          ;
          Object v = n.value;
          if (v == null) { // n is deleted
            n.helpDelete(b, f);
            break;
          }
          if (v == n || b.value == null) // b is deleted
            break;
          int c = key.compareTo(n.key);
          if (c > 0) {
            b = n;
            n = f;
            continue;
          }
          if (c == 0) {
            if (onlyIfAbsent || n.casValue(v, value))
              return (V) v;
            else
              break; // restart if lost race to replace value
          }
          // else c < 0; fall through
        }

        Node<K, V> z = new Node<K, V>(kkey, value, n);
        if (!b.casNext(n, z))
          break; // restart if lost race to append to b
        int level = randomLevel();
        if (level > 0)
          insertIndex(z, level);
        return null;
      }
    }
  }

  /**
   * Return a random level for inserting a new node. Hardwired to k=1, p=0.5,
   * max 31.
   * 
   * This uses a cheap pseudo-random function that according to
   * http://home1.gte.net/deleyd/random/random4.html was used in Turbo Pascal.
   * It seems the fastest usable one here. The low bits are apparently not very
   * random (the original used only upper 16 bits) so we traverse from highest
   * bit down (i.e., test sign), thus hardly ever use lower bits.
   */
  private int randomLevel() {
    int level = 0;
    int r = randomSeed;
    randomSeed = r * 134775813 + 1;
    if (r < 0) {
      while ((r <<= 1) > 0)
        ++level;
    }
    return level;
  }

  /**
   * Create and add index nodes for given node.
   * 
   * @param z
   *          the node
   * @param level
   *          the level of the index
   */
  private void insertIndex(Node<K, V> z, int level) {
    HeadIndex<K, V> h = head;
    int max = h.level;

    if (level <= max) {
      Index<K, V> idx = null;
      for (int i = 1; i <= level; ++i)
        idx = new Index<K, V>(z, idx, null);
      addIndex(idx, h, level);

    } else { // Add a new level
      /*
       * To reduce interference by other threads checking for empty levels in
       * tryReduceLevel, new levels are added with initialized right pointers.
       * Which in turn requires keeping levels in an array to access them while
       * creating new head index nodes from the opposite direction.
       */
      level = max + 1;
      Index<K, V>[] idxs = (Index<K, V>[]) new Index[level + 1];
      Index<K, V> idx = null;
      for (int i = 1; i <= level; ++i)
        idxs[i] = idx = new Index<K, V>(z, idx, null);

      HeadIndex<K, V> oldh;
      int k;
      for (;;) {
        oldh = head;
        int oldLevel = oldh.level;
        if (level <= oldLevel) { // lost race to add level
          k = level;
          break;
        }
        HeadIndex<K, V> newh = oldh;
        Node<K, V> oldbase = oldh.node;
        for (int j = oldLevel + 1; j <= level; ++j)
          newh = new HeadIndex<K, V>(oldbase, newh, idxs[j], j);
        if (casHead(oldh, newh)) {
          k = oldLevel;
          break;
        }
      }
      addIndex(idxs[k], oldh, k);
    }
  }

  /**
   * Add given index nodes from given level down to 1.
   * 
   * @param idx
   *          the topmost index node being inserted
   * @param h
   *          the value of head to use to insert. This must be snapshotted by
   *          callers to provide correct insertion level
   * @param indexLevel
   *          the level of the index
   */
  private void addIndex(Index<K, V> idx, HeadIndex<K, V> h, int indexLevel) {
    // Track next level to insert in case of retries
    int insertionLevel = indexLevel;
    Comparable<K> key = comparable(idx.key);

    // Similar to findPredecessor, but adding index nodes along
    // path to key.
    for (;;) {
      Index<K, V> q = h;
      Index<K, V> t = idx;
      int j = h.level;
      for (;;) {
        Index<K, V> r = q.right;
        if (r != null) {
          // compare before deletion check avoids needing recheck
          int c = key.compareTo(r.key);
          if (r.indexesDeletedNode()) {
            if (q.unlink(r))
              continue;
            else
              break;
          }
          if (c > 0) {
            q = r;
            continue;
          }
        }

        if (j == insertionLevel) {
          // Don't insert index if node already deleted
          if (t.indexesDeletedNode()) {
            findNode(key); // cleans up
            return;
          }
          if (!q.link(r, t))
            break; // restart
          if (--insertionLevel == 0) {
            // need final deletion check before return
            if (t.indexesDeletedNode())
              findNode(key);
            return;
          }
        }

        if (j > insertionLevel && j <= indexLevel)
          t = t.down;
        q = q.down;
        --j;
      }
    }
  }

  /* ---------------- Deletion -------------- */

  /**
   * Main deletion method. Locates node, nulls value, appends a deletion marker,
   * unlinks predecessor, removes associated index nodes, and possibly reduces
   * head index level.
   * 
   * Index nodes are cleared out simply by calling findPredecessor. which
   * unlinks indexes to deleted nodes found along path to key, which will
   * include the indexes to this node. This is done unconditionally. We can't
   * check beforehand whether there are index nodes because it might be the case
   * that some or all indexes hadn't been inserted yet for this node during
   * initial search for it, and we'd like to ensure lack of garbage retention,
   * so must call to be sure.
   * 
   * @param okey
   *          the key
   * @param value
   *          if non-null, the value that must be associated with key
   * @return the node, or null if not found
   */
  private V doRemove(Object okey, Object value) {
    Comparable<K> key = comparable(okey);
    for (;;) {
      Node<K, V> b = findPredecessor(key);
      Node<K, V> n = b.next;
      for (;;) {
        if (n == null)
          return null;
        Node<K, V> f = n.next;
        if (n != b.next) // inconsistent read
          break;
        Object v = n.value;
        if (v == null) { // n is deleted
          n.helpDelete(b, f);
          break;
        }
        if (v == n || b.value == null) // b is deleted
          break;
        int c = key.compareTo(n.key);
        if (c < 0)
          return null;
        if (c > 0) {
          b = n;
          n = f;
          continue;
        }
        if (value != null && !value.equals(v))
          return null;
        if (!n.casValue(v, null))
          break;
        if (!n.appendMarker(f) || !b.casNext(n, f))
          findNode(key); // Retry via findNode
        else {
          findPredecessor(key); // Clean index
          if (head.right == null)
            tryReduceLevel();
        }
        return (V) v;
      }
    }
  }

  /**
   * Possibly reduce head level if it has no nodes. This method can (rarely)
   * make mistakes, in which case levels can disappear even though they are
   * about to contain index nodes. This impacts performance, not correctness. To
   * minimize mistakes as well as to reduce hysteresis, the level is reduced by
   * one only if the topmost three levels look empty. Also, if the removed level
   * looks non-empty after CAS, we try to change it back quick before anyone
   * notices our mistake! (This trick works pretty well because this method will
   * practically never make mistakes unless current thread stalls immediately
   * before first CAS, in which case it is very unlikely to stall again
   * immediately afterwards, so will recover.)
   * 
   * We put up with all this rather than just let levels grow because otherwise,
   * even a small map that has undergone a large number of insertions and
   * removals will have a lot of levels, slowing down access more than would an
   * occasional unwanted reduction.
   */
  private void tryReduceLevel() {
    HeadIndex<K, V> h = head;
    HeadIndex<K, V> d;
    HeadIndex<K, V> e;
    if (h.level > 3 && (d = (HeadIndex<K, V>) h.down) != null
        && (e = (HeadIndex<K, V>) d.down) != null && e.right == null && d.right == null
        && h.right == null && casHead(h, d) && // try to set
        h.right != null) // recheck
      casHead(d, h); // try to backout
  }

  /**
   * Version of remove with boolean return. Needed by view classes
   */
  boolean removep(Object key) {
    return doRemove(key, null) != null;
  }

  /* ---------------- Finding and removing first element -------------- */

  /**
   * Specialized variant of findNode to get first valid node
   * 
   * @return first node or null if empty
   */
  Node<K, V> findFirst() {
    for (;;) {
      Node<K, V> b = head.node;
      Node<K, V> n = b.next;
      if (n == null)
        return null;
      if (n.value != null)
        return n;
      n.helpDelete(b, n.next);
    }
  }

  /**
   * Remove first entry; return either its key or a snapshot.
   * 
   * @param keyOnly
   *          if true return key, else return SnapshotEntry (This is a little
   *          ugly, but avoids code duplication.)
   * @return null if empty, first key if keyOnly true, else key,value entry
   */
  Object doRemoveFirst(boolean keyOnly) {
    for (;;) {
      Node<K, V> b = head.node;
      Node<K, V> n = b.next;
      if (n == null)
        return null;
      Node<K, V> f = n.next;
      if (n != b.next)
        continue;
      Object v = n.value;
      if (v == null) {
        n.helpDelete(b, f);
        continue;
      }
      if (!n.casValue(v, null))
        continue;
      if (!n.appendMarker(f) || !b.casNext(n, f))
        findFirst(); // retry
      clearIndexToFirst();
      K key = n.key;
      return (keyOnly) ? key : new SnapshotEntry<K, V>(key, (V) v);
    }
  }

  /**
   * Clear out index nodes associated with deleted first entry. Needed by
   * doRemoveFirst
   */
  private void clearIndexToFirst() {
    for (;;) {
      Index<K, V> q = head;
      for (;;) {
        Index<K, V> r = q.right;
        if (r != null && r.indexesDeletedNode() && !q.unlink(r))
          break;
        if ((q = q.down) == null) {
          if (head.right == null)
            tryReduceLevel();
          return;
        }
      }
    }
  }

  /**
   * Remove first entry; return key or null if empty.
   */
  K pollFirstKey() {
    return (K) doRemoveFirst(true);
  }

  /* ---------------- Finding and removing last element -------------- */

  /**
   * Specialized version of find to get last valid node
   * 
   * @return last node or null if empty
   */
  Node<K, V> findLast() {
    /*
     * findPredecessor can't be used to traverse index level because this
     * doesn't use comparisons. So traversals of both levels are folded
     * together.
     */
    Index<K, V> q = head;
    for (;;) {
      Index<K, V> d, r;
      if ((r = q.right) != null) {
        if (r.indexesDeletedNode()) {
          q.unlink(r);
          q = head; // restart
        } else
          q = r;
      } else if ((d = q.down) != null) {
        q = d;
      } else {
        Node<K, V> b = q.node;
        Node<K, V> n = b.next;
        for (;;) {
          if (n == null)
            return (b.isBaseHeader()) ? null : b;
          Node<K, V> f = n.next; // inconsistent read
          if (n != b.next)
            break;
          Object v = n.value;
          if (v == null) { // n is deleted
            n.helpDelete(b, f);
            break;
          }
          if (v == n || b.value == null) // b is deleted
            break;
          b = n;
          n = f;
        }
        q = head; // restart
      }
    }
  }

  /**
   * Specialized version of doRemove for last entry.
   * 
   * @param keyOnly
   *          if true return key, else return SnapshotEntry
   * @return null if empty, last key if keyOnly true, else key,value entry
   */
  Object doRemoveLast(boolean keyOnly) {
    for (;;) {
      Node<K, V> b = findPredecessorOfLast();
      Node<K, V> n = b.next;
      if (n == null) {
        if (b.isBaseHeader()) // empty
          return null;
        else
          continue; // all b's successors are deleted; retry
      }
      for (;;) {
        Node<K, V> f = n.next;
        if (n != b.next) // inconsistent read
          break;
        Object v = n.value;
        if (v == null) { // n is deleted
          n.helpDelete(b, f);
          break;
        }
        if (v == n || b.value == null) // b is deleted
          break;
        if (f != null) {
          b = n;
          n = f;
          continue;
        }
        if (!n.casValue(v, null))
          break;
        K key = n.key;
        Comparable<K> ck = comparable(key);
        if (!n.appendMarker(f) || !b.casNext(n, f))
          findNode(ck); // Retry via findNode
        else {
          findPredecessor(ck); // Clean index
          if (head.right == null)
            tryReduceLevel();
        }
        return (keyOnly) ? key : new SnapshotEntry<K, V>(key, (V) v);
      }
    }
  }

  /**
   * Specialized variant of findPredecessor to get predecessor of last valid
   * node. Needed by doRemoveLast. It is possible that all successors of
   * returned node will have been deleted upon return, in which case this method
   * can be retried.
   * 
   * @return likely predecessor of last node.
   */
  private Node<K, V> findPredecessorOfLast() {
    for (;;) {
      Index<K, V> q = head;
      for (;;) {
        Index<K, V> d, r;
        if ((r = q.right) != null) {
          if (r.indexesDeletedNode()) {
            q.unlink(r);
            break; // must restart
          }
          // proceed as far across as possible without overshooting
          if (r.node.next != null) {
            q = r;
            continue;
          }
        }
        if ((d = q.down) != null)
          q = d;
        else
          return q.node;
      }
    }
  }

  /**
   * Remove last entry; return key or null if empty.
   */
  K pollLastKey() {
    return (K) doRemoveLast(true);
  }

  /* ---------------- Relational operations -------------- */

  // Control values OR'ed as arguments to findNear
  private static final int EQ = 1;

  private static final int LT = 2;

  private static final int GT = 0; // Actually checked as !LT

  /**
   * Utility for ceiling, floor, lower, higher methods.
   * 
   * @param kkey
   *          the key
   * @param rel
   *          the relation -- OR'ed combination of EQ, LT, GT
   * @return nearest node fitting relation, or null if no such
   */
  Node<K, V> findNear(K kkey, int rel) {
    Comparable<K> key = comparable(kkey);
    for (;;) {
      Node<K, V> b = findPredecessor(key);
      Node<K, V> n = b.next;
      for (;;) {
        if (n == null)
          return ((rel & LT) == 0 || b.isBaseHeader()) ? null : b;
        Node<K, V> f = n.next;
        if (n != b.next) // inconsistent read
          break;
        Object v = n.value;
        if (v == null) { // n is deleted
          n.helpDelete(b, f);
          break;
        }
        if (v == n || b.value == null) // b is deleted
          break;
        int c = key.compareTo(n.key);
        if ((c == 0 && (rel & EQ) != 0) || (c < 0 && (rel & LT) == 0))
          return n;
        if (c <= 0 && (rel & LT) != 0)
          return (b.isBaseHeader()) ? null : b;
        b = n;
        n = f;
      }
    }
  }

  /**
   * Return SnapshotEntry for results of findNear.
   * 
   * @param kkey
   *          the key
   * @param rel
   *          the relation -- OR'ed combination of EQ, LT, GT
   * @return Entry fitting relation, or null if no such
   */
  SnapshotEntry<K, V> getNear(K kkey, int rel) {
    for (;;) {
      Node<K, V> n = findNear(kkey, rel);
      if (n == null)
        return null;
      SnapshotEntry<K, V> e = n.createSnapshot();
      if (e != null)
        return e;
    }
  }

  /**
   * Return ceiling, or first node if key is <tt>null</tt>
   */
  Node<K, V> findCeiling(K key) {
    return (key == null) ? findFirst() : findNear(key, GT | EQ);
  }

  /**
   * Return lower node, or last node if key is <tt>null</tt>
   */
  Node<K, V> findLower(K key) {
    return (key == null) ? findLast() : findNear(key, LT);
  }

  /**
   * Return SnapshotEntry or key for results of findNear ofter screening to
   * ensure result is in given range. Needed by submaps.
   * 
   * @param kkey
   *          the key
   * @param rel
   *          the relation -- OR'ed combination of EQ, LT, GT
   * @param least
   *          minimum allowed key value
   * @param fence
   *          key greater than maximum allowed key value
   * @param keyOnly
   *          if true return key, else return SnapshotEntry
   * @return Key or Entry fitting relation, or <tt>null</tt> if no such
   */
  Object getNear(K kkey, int rel, K least, K fence, boolean keyOnly) {
    K key = kkey;
    // Don't return keys less than least
    if ((rel & LT) == 0) {
      if (compare(key, least) < 0) {
        key = least;
        rel = rel | EQ;
      }
    }

    for (;;) {
      Node<K, V> n = findNear(key, rel);
      if (n == null || !inHalfOpenRange(n.key, least, fence))
        return null;
      K k = n.key;
      V v = n.getValidValue();
      if (v != null)
        return keyOnly ? k : new SnapshotEntry<K, V>(k, v);
    }
  }

  /**
   * Find and remove least element of subrange.
   * 
   * @param least
   *          minimum allowed key value
   * @param fence
   *          key greater than maximum allowed key value
   * @param keyOnly
   *          if true return key, else return SnapshotEntry
   * @return least Key or Entry, or <tt>null</tt> if no such
   */
  Object removeFirstEntryOfSubrange(K least, K fence, boolean keyOnly) {
    for (;;) {
      Node<K, V> n = findCeiling(least);
      if (n == null)
        return null;
      K k = n.key;
      if (fence != null && compare(k, fence) >= 0)
        return null;
      V v = doRemove(k, null);
      if (v != null)
        return (keyOnly) ? k : new SnapshotEntry<K, V>(k, v);
    }
  }

  /**
   * Find and remove greatest element of subrange.
   * 
   * @param least
   *          minimum allowed key value
   * @param fence
   *          key greater than maximum allowed key value
   * @param keyOnly
   *          if true return key, else return SnapshotEntry
   * @return least Key or Entry, or <tt>null</tt> if no such
   */
  Object removeLastEntryOfSubrange(K least, K fence, boolean keyOnly) {
    for (;;) {
      Node<K, V> n = findLower(fence);
      if (n == null)
        return null;
      K k = n.key;
      if (least != null && compare(k, least) < 0)
        return null;
      V v = doRemove(k, null);
      if (v != null)
        return (keyOnly) ? k : new SnapshotEntry<K, V>(k, v);
    }
  }

  /* ---------------- Constructors -------------- */

  /**
   * Constructs a new empty map, sorted according to the keys' natural order.
   */
  public ConcurrentSkipListMap() {
    this.comparator = null;
    initialize();
  }

  /**
   * Constructs a new empty map, sorted according to the given comparator.
   * 
   * @param c
   *          the comparator that will be used to sort this map. A <tt>null</tt>
   *          value indicates that the keys' <i>natural ordering</i> should be
   *          used.
   */
  public ConcurrentSkipListMap(Comparator<? super K> c) {
    this.comparator = c;
    initialize();
  }

  /**
   * Constructs a new map containing the same mappings as the given map, sorted
   * according to the keys' <i>natural order</i>.
   * 
   * @param m
   *          the map whose mappings are to be placed in this map.
   * @throws ClassCastException
   *           if the keys in m are not Comparable, or are not mutually
   *           comparable.
   * @throws NullPointerException
   *           if the specified map is <tt>null</tt>.
   */
  public ConcurrentSkipListMap(Map<? extends K, ? extends V> m) {
    this.comparator = null;
    initialize();
    putAll(m);
  }

  /**
   * Constructs a new map containing the same mappings as the given
   * <tt>SortedMap</tt>, sorted according to the same ordering.
   * 
   * @param m
   *          the sorted map whose mappings are to be placed in this map, and
   *          whose comparator is to be used to sort this map.
   * @throws NullPointerException
   *           if the specified sorted map is <tt>null</tt>.
   */
  public ConcurrentSkipListMap(SortedMap<K, ? extends V> m) {
    this.comparator = m.comparator();
    initialize();
    buildFromSorted(m);
  }

  /**
   * Returns a shallow copy of this <tt>Map</tt> instance. (The keys and
   * values themselves are not cloned.)
   * 
   * @return a shallow copy of this Map.
   */
  public Object clone() {
    ConcurrentSkipListMap<K, V> clone = null;
    try {
      clone = (ConcurrentSkipListMap<K, V>) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new InternalError();
    }

    clone.initialize();
    clone.buildFromSorted(this);
    return clone;
  }

  /**
   * Streamlined bulk insertion to initialize from elements of given sorted map.
   * Call only from constructor or clone method.
   */
  private void buildFromSorted(SortedMap<K, ? extends V> map) {
    if (map == null)
      throw new NullPointerException();

    HeadIndex<K, V> h = head;
    Node<K, V> basepred = h.node;

    // Track the current rightmost node at each level. Uses an
    // ArrayList to avoid committing to initial or maximum level.
    ArrayList<Index<K, V>> preds = new ArrayList<Index<K, V>>();

    // initialize
    for (int i = 0; i <= h.level; ++i)
      preds.add(null);
    Index<K, V> q = h;
    for (int i = h.level; i > 0; --i) {
      preds.set(i, q);
      q = q.down;
    }

    Iterator<? extends Map.Entry<? extends K, ? extends V>> it = map.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry<? extends K, ? extends V> e = it.next();
      int j = randomLevel();
      if (j > h.level)
        j = h.level + 1;
      K k = e.getKey();
      V v = e.getValue();
      if (k == null || v == null)
        throw new NullPointerException();
      Node<K, V> z = new Node<K, V>(k, v, null);
      basepred.next = z;
      basepred = z;
      if (j > 0) {
        Index<K, V> idx = null;
        for (int i = 1; i <= j; ++i) {
          idx = new Index<K, V>(z, idx, null);
          if (i > h.level)
            h = new HeadIndex<K, V>(h.node, h, idx, i);

          if (i < preds.size()) {
            preds.get(i).right = idx;
            preds.set(i, idx);
          } else
            preds.add(idx);
        }
      }
    }
    head = h;
  }

  /* ---------------- Serialization -------------- */

  /**
   * Save the state of the <tt>Map</tt> instance to a stream.
   * 
   * @serialData The key (Object) and value (Object) for each key-value mapping
   *             represented by the Map, followed by <tt>null</tt>. The
   *             key-value mappings are emitted in key-order (as determined by
   *             the Comparator, or by the keys' natural ordering if no
   *             Comparator).
   */
  private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
    // Write out the Comparator and any hidden stuff
    s.defaultWriteObject();

    // Write out keys and values (alternating)
    for (Node<K, V> n = findFirst(); n != null; n = n.next) {
      V v = n.getValidValue();
      if (v != null) {
        s.writeObject(n.key);
        s.writeObject(v);
      }
    }
    s.writeObject(null);
  }

  /**
   * Reconstitute the <tt>Map</tt> instance from a stream.
   */
  private void readObject(final java.io.ObjectInputStream s) throws java.io.IOException,
      ClassNotFoundException {
    // Read in the Comparator and any hidden stuff
    s.defaultReadObject();
    // Reset transients
    initialize();

    /*
     * This is nearly identical to buildFromSorted, but is distinct because
     * readObject calls can't be nicely adapted as the kind of iterator needed
     * by buildFromSorted. (They can be, but doing so requires type cheats
     * and/or creation of adaptor classes.) It is simpler to just adapt the
     * code.
     */

    HeadIndex<K, V> h = head;
    Node<K, V> basepred = h.node;
    ArrayList<Index<K, V>> preds = new ArrayList<Index<K, V>>();
    for (int i = 0; i <= h.level; ++i)
      preds.add(null);
    Index<K, V> q = h;
    for (int i = h.level; i > 0; --i) {
      preds.set(i, q);
      q = q.down;
    }

    for (;;) {
      Object k = s.readObject();
      if (k == null)
        break;
      Object v = s.readObject();
      if (v == null)
        throw new NullPointerException();
      K key = (K) k;
      V val = (V) v;
      int j = randomLevel();
      if (j > h.level)
        j = h.level + 1;
      Node<K, V> z = new Node<K, V>(key, val, null);
      basepred.next = z;
      basepred = z;
      if (j > 0) {
        Index<K, V> idx = null;
        for (int i = 1; i <= j; ++i) {
          idx = new Index<K, V>(z, idx, null);
          if (i > h.level)
            h = new HeadIndex<K, V>(h.node, h, idx, i);

          if (i < preds.size()) {
            preds.get(i).right = idx;
            preds.set(i, idx);
          } else
            preds.add(idx);
        }
      }
    }
    head = h;
  }

  /* ------ Map API methods ------ */

  /**
   * Returns <tt>true</tt> if this map contains a mapping for the specified
   * key.
   * 
   * @param key
   *          key whose presence in this map is to be tested.
   * @return <tt>true</tt> if this map contains a mapping for the specified
   *         key.
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key is <tt>null</tt>.
   */
  public boolean containsKey(Object key) {
    return doGet(key) != null;
  }

  /**
   * Returns the value to which this map maps the specified key. Returns
   * <tt>null</tt> if the map contains no mapping for this key.
   * 
   * @param key
   *          key whose associated value is to be returned.
   * @return the value to which this map maps the specified key, or
   *         <tt>null</tt> if the map contains no mapping for the key.
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key is <tt>null</tt>.
   */
  public V get(Object key) {
    return doGet(key);
  }

  /**
   * Associates the specified value with the specified key in this map. If the
   * map previously contained a mapping for this key, the old value is replaced.
   * 
   * @param key
   *          key with which the specified value is to be associated.
   * @param value
   *          value to be associated with the specified key.
   * 
   * @return previous value associated with specified key, or <tt>null</tt> if
   *         there was no mapping for key.
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key or value are <tt>null</tt>.
   */
  public V put(K key, V value) {
    if (value == null)
      throw new NullPointerException();
    return doPut(key, value, false);
  }

  /**
   * Removes the mapping for this key from this Map if present.
   * 
   * @param key
   *          key for which mapping should be removed
   * @return previous value associated with specified key, or <tt>null</tt> if
   *         there was no mapping for key.
   * 
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key is <tt>null</tt>.
   */
  public V remove(Object key) {
    return doRemove(key, null);
  }

  /**
   * Returns <tt>true</tt> if this map maps one or more keys to the specified
   * value. This operation requires time linear in the Map size.
   * 
   * @param value
   *          value whose presence in this Map is to be tested.
   * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
   *         <tt>false</tt> otherwise.
   * @throws NullPointerException
   *           if the value is <tt>null</tt>.
   */
  public boolean containsValue(Object value) {
    if (value == null)
      throw new NullPointerException();
    for (Node<K, V> n = findFirst(); n != null; n = n.next) {
      V v = n.getValidValue();
      if (v != null && value.equals(v))
        return true;
    }
    return false;
  }

  /**
   * Returns the number of elements in this map. If this map contains more than
   * <tt>Integer.MAX_VALUE</tt> elements, it returns
   * <tt>Integer.MAX_VALUE</tt>.
   * 
   * <p>
   * Beware that, unlike in most collections, this method is <em>NOT</em> a
   * constant-time operation. Because of the asynchronous nature of these maps,
   * determining the current number of elements requires traversing them all to
   * count them. Additionally, it is possible for the size to change during
   * execution of this method, in which case the returned result will be
   * inaccurate. Thus, this method is typically not very useful in concurrent
   * applications.
   * 
   * @return the number of elements in this map.
   */
  public int size() {
    long count = 0;
    for (Node<K, V> n = findFirst(); n != null; n = n.next) {
      if (n.getValidValue() != null)
        ++count;
    }
    return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count;
  }

  /**
   * Returns <tt>true</tt> if this map contains no key-value mappings.
   * 
   * @return <tt>true</tt> if this map contains no key-value mappings.
   */
  public boolean isEmpty() {
    return findFirst() == null;
  }

  /**
   * Removes all mappings from this map.
   */
  public void clear() {
    initialize();
  }

  /**
   * Returns a set view of the keys contained in this map. The set is backed by
   * the map, so changes to the map are reflected in the set, and vice-versa.
   * The set supports element removal, which removes the corresponding mapping
   * from this map, via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
   * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
   * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
   * operations. The view's <tt>iterator</tt> is a "weakly consistent"
   * iterator that will never throw
   * {@link java.util.ConcurrentModificationException}, and guarantees to
   * traverse elements as they existed upon construction of the iterator, and
   * may (but is not guaranteed to) reflect any modifications subsequent to
   * construction.
   * 
   * @return a set view of the keys contained in this map.
   */
  public Set<K> keySet() {
    /*
     * Note: Lazy intialization works here and for other views because view
     * classes are stateless/immutable so it doesn't matter wrt correctness if
     * more than one is created (which will only rarely happen). Even so, the
     * following idiom conservatively ensures that the method returns the one it
     * created if it does so, not one created by another racing thread.
     */
    KeySet ks = keySet;
    return (ks != null) ? ks : (keySet = new KeySet());
  }

  /**
   * Returns a set view of the keys contained in this map in descending order.
   * The set is backed by the map, so changes to the map are reflected in the
   * set, and vice-versa. The set supports element removal, which removes the
   * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
   * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
   * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
   * <tt>addAll</tt> operations. The view's <tt>iterator</tt> is a "weakly
   * consistent" iterator that will never throw
   * {@link java.util.ConcurrentModificationException}, and guarantees to
   * traverse elements as they existed upon construction of the iterator, and
   * may (but is not guaranteed to) reflect any modifications subsequent to
   * construction.
   * 
   * @return a set view of the keys contained in this map.
   */
  public Set<K> descendingKeySet() {
    /*
     * Note: Lazy intialization works here and for other views because view
     * classes are stateless/immutable so it doesn't matter wrt correctness if
     * more than one is created (which will only rarely happen). Even so, the
     * following idiom conservatively ensures that the method returns the one it
     * created if it does so, not one created by another racing thread.
     */
    DescendingKeySet ks = descendingKeySet;
    return (ks != null) ? ks : (descendingKeySet = new DescendingKeySet());
  }

  /**
   * Returns a collection view of the values contained in this map. The
   * collection is backed by the map, so changes to the map are reflected in the
   * collection, and vice-versa. The collection supports element removal, which
   * removes the corresponding mapping from this map, via the
   * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
   * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
   * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
   * operations. The view's <tt>iterator</tt> is a "weakly consistent"
   * iterator that will never throw {@link
   * java.util.ConcurrentModificationException}, and guarantees to traverse
   * elements as they existed upon construction of the iterator, and may (but is
   * not guaranteed to) reflect any modifications subsequent to construction.
   * 
   * @return a collection view of the values contained in this map.
   */
  public Collection<V> values() {
    Values vs = values;
    return (vs != null) ? vs : (values = new Values());
  }

  /**
   * Returns a collection view of the mappings contained in this map. Each
   * element in the returned collection is a <tt>Map.Entry</tt>. The
   * collection is backed by the map, so changes to the map are reflected in the
   * collection, and vice-versa. The collection supports element removal, which
   * removes the corresponding mapping from the map, via the
   * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
   * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
   * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
   * operations. The view's <tt>iterator</tt> is a "weakly consistent"
   * iterator that will never throw {@link
   * java.util.ConcurrentModificationException}, and guarantees to traverse
   * elements as they existed upon construction of the iterator, and may (but is
   * not guaranteed to) reflect any modifications subsequent to construction.
   * The <tt>Map.Entry</tt> elements returned by <tt>iterator.next()</tt> do
   * <em>not</em> support the <tt>setValue</tt> operation.
   * 
   * @return a collection view of the mappings contained in this map.
   */
  public Set<Map.Entry<K, V>> entrySet() {
    EntrySet es = entrySet;
    return (es != null) ? es : (entrySet = new EntrySet());
  }

  /**
   * Returns a collection view of the mappings contained in this map, in
   * descending order. Each element in the returned collection is a
   * <tt>Map.Entry</tt>. The collection is backed by the map, so changes to
   * the map are reflected in the collection, and vice-versa. The collection
   * supports element removal, which removes the corresponding mapping from the
   * map, via the <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
   * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
   * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
   * operations. The view's <tt>iterator</tt> is a "weakly consistent"
   * iterator that will never throw {@link
   * java.util.ConcurrentModificationException}, and guarantees to traverse
   * elements as they existed upon construction of the iterator, and may (but is
   * not guaranteed to) reflect any modifications subsequent to construction.
   * The <tt>Map.Entry</tt> elements returned by <tt>iterator.next()</tt> do
   * <em>not</em> support the <tt>setValue</tt> operation.
   * 
   * @return a collection view of the mappings contained in this map.
   */
  public Set<Map.Entry<K, V>> descendingEntrySet() {
    DescendingEntrySet es = descendingEntrySet;
    return (es != null) ? es : (descendingEntrySet = new DescendingEntrySet());
  }

  /* ---------------- AbstractMap Overrides -------------- */

  /**
   * Compares the specified object with this map for equality. Returns
   * <tt>true</tt> if the given object is also a map and the two maps
   * represent the same mappings. More formally, two maps <tt>t1</tt> and
   * <tt>t2</tt> represent the same mappings if
   * <tt>t1.keySet().equals(t2.keySet())</tt> and for every key <tt>k</tt>
   * in <tt>t1.keySet()</tt>, <tt> (t1.get(k)==null ?
   * t2.get(k)==null : t1.get(k).equals(t2.get(k))) </tt>.
   * This operation may return misleading results if either map is concurrently
   * modified during execution of this method.
   * 
   * @param o
   *          object to be compared for equality with this map.
   * @return <tt>true</tt> if the specified object is equal to this map.
   */
  public boolean equals(Object o) {
    if (o == this)
      return true;
    if (!(o instanceof Map))
      return false;
    Map<K, V> t = (Map<K, V>) o;
    try {
      return (containsAllMappings(this, t) && containsAllMappings(t, this));
    } catch (ClassCastException unused) {
      return false;
    } catch (NullPointerException unused) {
      return false;
    }
  }

  /**
   * Helper for equals -- check for containment, avoiding nulls.
   */
  static <K, V> boolean containsAllMappings(Map<K, V> a, Map<K, V> b) {
    Iterator<Entry<K, V>> it = b.entrySet().iterator();
    while (it.hasNext()) {
      Entry<K, V> e = it.next();
      Object k = e.getKey();
      Object v = e.getValue();
      if (k == null || v == null || !v.equals(a.get(k)))
        return false;
    }
    return true;
  }

  /* ------ ConcurrentMap API methods ------ */

  /**
   * If the specified key is not already associated with a value, associate it
   * with the given value. This is equivalent to
   * 
   * <pre>
   * if (!map.containsKey(key))
   *   return map.put(key, value);
   * else
   *   return map.get(key);
   * </pre>
   * 
   * except that the action is performed atomically.
   * 
   * @param key
   *          key with which the specified value is to be associated.
   * @param value
   *          value to be associated with the specified key.
   * @return previous value associated with specified key, or <tt>null</tt> if
   *         there was no mapping for key.
   * 
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key or value are <tt>null</tt>.
   */
  public V putIfAbsent(K key, V value) {
    if (value == null)
      throw new NullPointerException();
    return doPut(key, value, true);
  }

  /**
   * Remove entry for key only if currently mapped to given value. Acts as
   * 
   * <pre>
   *   if ((map.containsKey(key) &amp;&amp; map.get(key).equals(value)) {
   *      map.remove(key);
   *      return true;
   *  } else return false;
   * </pre>
   * 
   * except that the action is performed atomically.
   * 
   * @param key
   *          key with which the specified value is associated.
   * @param value
   *          value associated with the specified key.
   * @return true if the value was removed, false otherwise
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key or value are <tt>null</tt>.
   */
  public boolean remove(Object key, Object value) {
    if (value == null)
      throw new NullPointerException();
    return doRemove(key, value) != null;
  }

  /**
   * Replace entry for key only if currently mapped to given value. Acts as
   * 
   * <pre>
   *   if ((map.containsKey(key) &amp;&amp; map.get(key).equals(oldValue)) {
   *      map.put(key, newValue);
   *      return true;
   *  } else return false;
   * </pre>
   * 
   * except that the action is performed atomically.
   * 
   * @param key
   *          key with which the specified value is associated.
   * @param oldValue
   *          value expected to be associated with the specified key.
   * @param newValue
   *          value to be associated with the specified key.
   * @return true if the value was replaced
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key, oldValue or newValue are <tt>null</tt>.
   */
  public boolean replace(K key, V oldValue, V newValue) {
    if (oldValue == null || newValue == null)
      throw new NullPointerException();
    Comparable<K> k = comparable(key);
    for (;;) {
      Node<K, V> n = findNode(k);
      if (n == null)
        return false;
      Object v = n.value;
      if (v != null) {
        if (!oldValue.equals(v))
          return false;
        if (n.casValue(v, newValue))
          return true;
      }
    }
  }

  /**
   * Replace entry for key only if currently mapped to some value. Acts as
   * 
   * <pre>
   *   if ((map.containsKey(key)) {
   *      return map.put(key, value);
   *  } else return null;
   * </pre>
   * 
   * except that the action is performed atomically.
   * 
   * @param key
   *          key with which the specified value is associated.
   * @param value
   *          value to be associated with the specified key.
   * @return previous value associated with specified key, or <tt>null</tt> if
   *         there was no mapping for key.
   * @throws ClassCastException
   *           if the key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if the key or value are <tt>null</tt>.
   */
  public V replace(K key, V value) {
    if (value == null)
      throw new NullPointerException();
    Comparable<K> k = comparable(key);
    for (;;) {
      Node<K, V> n = findNode(k);
      if (n == null)
        return null;
      Object v = n.value;
      if (v != null && n.casValue(v, value))
        return (V) v;
    }
  }

  /* ------ SortedMap API methods ------ */

  /**
   * Returns the comparator used to order this map, or <tt>null</tt> if this
   * map uses its keys' natural order.
   * 
   * @return the comparator associated with this map, or <tt>null</tt> if it
   *         uses its keys' natural sort method.
   */
  public Comparator<? super K> comparator() {
    return comparator;
  }

  /**
   * Returns the first (lowest) key currently in this map.
   * 
   * @return the first (lowest) key currently in this map.
   * @throws NoSuchElementException
   *           Map is empty.
   */
  public K firstKey() {
    Node<K, V> n = findFirst();
    if (n == null)
      throw new NoSuchElementException();
    return n.key;
  }

  /**
   * Returns the last (highest) key currently in this map.
   * 
   * @return the last (highest) key currently in this map.
   * @throws NoSuchElementException
   *           Map is empty.
   */
  public K lastKey() {
    Node<K, V> n = findLast();
    if (n == null)
      throw new NoSuchElementException();
    return n.key;
  }

  /**
   * Returns a view of the portion of this map whose keys range from
   * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive. (If
   * <tt>fromKey</tt> and <tt>toKey</tt> are equal, the returned sorted map
   * is empty.) The returned sorted map is backed by this map, so changes in the
   * returned sorted map are reflected in this map, and vice-versa.
   * 
   * @param fromKey
   *          low endpoint (inclusive) of the subMap.
   * @param toKey
   *          high endpoint (exclusive) of the subMap.
   * 
   * @return a view of the portion of this map whose keys range from
   *         <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive.
   * 
   * @throws ClassCastException
   *           if <tt>fromKey</tt> and <tt>toKey</tt> cannot be compared to
   *           one another using this map's comparator (or, if the map has no
   *           comparator, using natural ordering).
   * @throws IllegalArgumentException
   *           if <tt>fromKey</tt> is greater than <tt>toKey</tt>.
   * @throws NullPointerException
   *           if <tt>fromKey</tt> or <tt>toKey</tt> is <tt>null</tt>.
   */
  public ConcurrentNavigableMap<K, V> subMap(K fromKey, K toKey) {
    if (fromKey == null || toKey == null)
      throw new NullPointerException();
    return new ConcurrentSkipListSubMap(this, fromKey, toKey);
  }

  /**
   * Returns a view of the portion of this map whose keys are strictly less than
   * <tt>toKey</tt>. The returned sorted map is backed by this map, so
   * changes in the returned sorted map are reflected in this map, and
   * vice-versa.
   * 
   * @param toKey
   *          high endpoint (exclusive) of the headMap.
   * @return a view of the portion of this map whose keys are strictly less than
   *         <tt>toKey</tt>.
   * 
   * @throws ClassCastException
   *           if <tt>toKey</tt> is not compatible with this map's comparator
   *           (or, if the map has no comparator, if <tt>toKey</tt> does not
   *           implement <tt>Comparable</tt>).
   * @throws NullPointerException
   *           if <tt>toKey</tt> is <tt>null</tt>.
   */
  public ConcurrentNavigableMap<K, V> headMap(K toKey) {
    if (toKey == null)
      throw new NullPointerException();
    return new ConcurrentSkipListSubMap(this, null, toKey);
  }

  /**
   * Returns a view of the portion of this map whose keys are greater than or
   * equal to <tt>fromKey</tt>. The returned sorted map is backed by this
   * map, so changes in the returned sorted map are reflected in this map, and
   * vice-versa.
   * 
   * @param fromKey
   *          low endpoint (inclusive) of the tailMap.
   * @return a view of the portion of this map whose keys are greater than or
   *         equal to <tt>fromKey</tt>.
   * @throws ClassCastException
   *           if <tt>fromKey</tt> is not compatible with this map's
   *           comparator (or, if the map has no comparator, if <tt>fromKey</tt>
   *           does not implement <tt>Comparable</tt>).
   * @throws NullPointerException
   *           if <tt>fromKey</tt> is <tt>null</tt>.
   */
  public ConcurrentNavigableMap<K, V> tailMap(K fromKey) {
    if (fromKey == null)
      throw new NullPointerException();
    return new ConcurrentSkipListSubMap(this, fromKey, null);
  }

  /* ---------------- Relational operations -------------- */

  /**
   * Returns a key-value mapping associated with the least key greater than or
   * equal to the given key, or <tt>null</tt> if there is no such entry. The
   * returned entry does <em>not</em> support the <tt>Entry.setValue</tt>
   * method.
   * 
   * @param key
   *          the key.
   * @return an Entry associated with ceiling of given key, or <tt>null</tt>
   *         if there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public Map.Entry<K, V> ceilingEntry(K key) {
    return getNear(key, GT | EQ);
  }

  /**
   * Returns least key greater than or equal to the given key, or <tt>null</tt>
   * if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the ceiling key, or <tt>null</tt> if there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public K ceilingKey(K key) {
    Node<K, V> n = findNear(key, GT | EQ);
    return (n == null) ? null : n.key;
  }

  /**
   * Returns a key-value mapping associated with the greatest key strictly less
   * than the given key, or <tt>null</tt> if there is no such entry. The
   * returned entry does <em>not</em> support the <tt>Entry.setValue</tt>
   * method.
   * 
   * @param key
   *          the key.
   * @return an Entry with greatest key less than the given key, or
   *         <tt>null</tt> if there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public Map.Entry<K, V> lowerEntry(K key) {
    return getNear(key, LT);
  }

  /**
   * Returns the greatest key strictly less than the given key, or <tt>null</tt>
   * if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the greatest key less than the given key, or <tt>null</tt> if
   *         there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public K lowerKey(K key) {
    Node<K, V> n = findNear(key, LT);
    return (n == null) ? null : n.key;
  }

  /**
   * Returns a key-value mapping associated with the greatest key less than or
   * equal to the given key, or <tt>null</tt> if there is no such entry. The
   * returned entry does <em>not</em> support the <tt>Entry.setValue</tt>
   * method.
   * 
   * @param key
   *          the key.
   * @return an Entry associated with floor of given key, or <tt>null</tt> if
   *         there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public Map.Entry<K, V> floorEntry(K key) {
    return getNear(key, LT | EQ);
  }

  /**
   * Returns the greatest key less than or equal to the given key, or
   * <tt>null</tt> if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the floor of given key, or <tt>null</tt> if there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public K floorKey(K key) {
    Node<K, V> n = findNear(key, LT | EQ);
    return (n == null) ? null : n.key;
  }

  /**
   * Returns a key-value mapping associated with the least key strictly greater
   * than the given key, or <tt>null</tt> if there is no such entry. The
   * returned entry does <em>not</em> support the <tt>Entry.setValue</tt>
   * method.
   * 
   * @param key
   *          the key.
   * @return an Entry with least key greater than the given key, or
   *         <tt>null</tt> if there is no such Entry.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public Map.Entry<K, V> higherEntry(K key) {
    return getNear(key, GT);
  }

  /**
   * Returns the least key strictly greater than the given key, or <tt>null</tt>
   * if there is no such key.
   * 
   * @param key
   *          the key.
   * @return the least key greater than the given key, or <tt>null</tt> if
   *         there is no such key.
   * @throws ClassCastException
   *           if key cannot be compared with the keys currently in the map.
   * @throws NullPointerException
   *           if key is <tt>null</tt>.
   */
  public K higherKey(K key) {
    Node<K, V> n = findNear(key, GT);
    return (n == null) ? null : n.key;
  }

  /**
   * Returns a key-value mapping associated with the least key in this map, or
   * <tt>null</tt> if the map is empty. The returned entry does <em>not</em>
   * support the <tt>Entry.setValue</tt> method.
   * 
   * @return an Entry with least key, or <tt>null</tt> if the map is empty.
   */
  public Map.Entry<K, V> firstEntry() {
    for (;;) {
      Node<K, V> n = findFirst();
      if (n == null)
        return null;
      SnapshotEntry<K, V> e = n.createSnapshot();
      if (e != null)
        return e;
    }
  }

  /**
   * Returns a key-value mapping associated with the greatest key in this map,
   * or <tt>null</tt> if the map is empty. The returned entry does
   * <em>not</em> support the <tt>Entry.setValue</tt> method.
   * 
   * @return an Entry with greatest key, or <tt>null</tt> if the map is empty.
   */
  public Map.Entry<K, V> lastEntry() {
    for (;;) {
      Node<K, V> n = findLast();
      if (n == null)
        return null;
      SnapshotEntry<K, V> e = n.createSnapshot();
      if (e != null)
        return e;
    }
  }

  /**
   * Removes and returns a key-value mapping associated with the least key in
   * this map, or <tt>null</tt> if the map is empty. The returned entry does
   * <em>not</em> support the <tt>Entry.setValue</tt> method.
   * 
   * @return the removed first entry of this map, or <tt>null</tt> if the map
   *         is empty.
   */
  public Map.Entry<K, V> pollFirstEntry() {
    return (SnapshotEntry<K, V>) doRemoveFirst(false);
  }

  /**
   * Removes and returns a key-value mapping associated with the greatest key in
   * this map, or <tt>null</tt> if the map is empty. The returned entry does
   * <em>not</em> support the <tt>Entry.setValue</tt> method.
   * 
   * @return the removed last entry of this map, or <tt>null</tt> if the map
   *         is empty.
   */
  public Map.Entry<K, V> pollLastEntry() {
    return (SnapshotEntry<K, V>) doRemoveLast(false);
  }

  /* ---------------- Iterators -------------- */

  /**
   * Base of ten kinds of iterator classes: ascending: {map, submap} X {key,
   * value, entry} descending: {map, submap} X {key, entry}
   */
  abstract class Iter {
    /** the last node returned by next() */
    Node<K, V> last;

    /** the next node to return from next(); */
    Node<K, V> next;

    /** Cache of next value field to maintain weak consistency */
    Object nextValue;

    Iter() {
    }

    public final boolean hasNext() {
      return next != null;
    }

    /** initialize ascending iterator for entire range */
    final void initAscending() {
      for (;;) {
        next = findFirst();
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next)
          break;
      }
    }

    /**
     * initialize ascending iterator starting at given least key, or first node
     * if least is <tt>null</tt>, but not greater or equal to fence, or end
     * if fence is <tt>null</tt>.
     */
    final void initAscending(K least, K fence) {
      for (;;) {
        next = findCeiling(least);
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next) {
          if (fence != null && compare(fence, next.key) <= 0) {
            next = null;
            nextValue = null;
          }
          break;
        }
      }
    }

    /** advance next to higher entry */
    final void ascend() {
      if ((last = next) == null)
        throw new NoSuchElementException();
      for (;;) {
        next = next.next;
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next)
          break;
      }
    }

    /**
     * Version of ascend for submaps to stop at fence
     */
    final void ascend(K fence) {
      if ((last = next) == null)
        throw new NoSuchElementException();
      for (;;) {
        next = next.next;
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next) {
          if (fence != null && compare(fence, next.key) <= 0) {
            next = null;
            nextValue = null;
          }
          break;
        }
      }
    }

    /** initialize descending iterator for entire range */
    final void initDescending() {
      for (;;) {
        next = findLast();
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next)
          break;
      }
    }

    /**
     * initialize descending iterator starting at key less than or equal to
     * given fence key, or last node if fence is <tt>null</tt>, but not less
     * than least, or beginning if lest is <tt>null</tt>.
     */
    final void initDescending(K least, K fence) {
      for (;;) {
        next = findLower(fence);
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next) {
          if (least != null && compare(least, next.key) > 0) {
            next = null;
            nextValue = null;
          }
          break;
        }
      }
    }

    /** advance next to lower entry */
    final void descend() {
      if ((last = next) == null)
        throw new NoSuchElementException();
      K k = last.key;
      for (;;) {
        next = findNear(k, LT);
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next)
          break;
      }
    }

    /**
     * Version of descend for submaps to stop at least
     */
    final void descend(K least) {
      if ((last = next) == null)
        throw new NoSuchElementException();
      K k = last.key;
      for (;;) {
        next = findNear(k, LT);
        if (next == null)
          break;
        nextValue = next.value;
        if (nextValue != null && nextValue != next) {
          if (least != null && compare(least, next.key) > 0) {
            next = null;
            nextValue = null;
          }
          break;
        }
      }
    }

    public void remove() {
      Node<K, V> l = last;
      if (l == null)
        throw new IllegalStateException();
      // It would not be worth all of the overhead to directly
      // unlink from here. Using remove is fast enough.
      ConcurrentSkipListMap.this.remove(l.key);
    }

  }

  final class ValueIterator extends Iter implements Iterator<V> {
    ValueIterator() {
      initAscending();
    }

    public V next() {
      Object v = nextValue;
      ascend();
      return (V) v;
    }
  }

  final class KeyIterator extends Iter implements Iterator<K> {
    KeyIterator() {
      initAscending();
    }

    public K next() {
      Node<K, V> n = next;
      ascend();
      return n.key;
    }
  }

  class SubMapValueIterator extends Iter implements Iterator<V> {
    final K fence;

    SubMapValueIterator(K least, K fence) {
      initAscending(least, fence);
      this.fence = fence;
    }

    public V next() {
      Object v = nextValue;
      ascend(fence);
      return (V) v;
    }
  }

  final class SubMapKeyIterator extends Iter implements Iterator<K> {
    final K fence;

    SubMapKeyIterator(K least, K fence) {
      initAscending(least, fence);
      this.fence = fence;
    }

    public K next() {
      Node<K, V> n = next;
      ascend(fence);
      return n.key;
    }
  }

  final class DescendingKeyIterator extends Iter implements Iterator<K> {
    DescendingKeyIterator() {
      initDescending();
    }

    public K next() {
      Node<K, V> n = next;
      descend();
      return n.key;
    }
  }

  final class DescendingSubMapKeyIterator extends Iter implements Iterator<K> {
    final K least;

    DescendingSubMapKeyIterator(K least, K fence) {
      initDescending(least, fence);
      this.least = least;
    }

    public K next() {
      Node<K, V> n = next;
      descend(least);
      return n.key;
    }
  }

  /**
   * Entry iterators use the same trick as in ConcurrentHashMap and elsewhere of
   * using the iterator itself to represent entries, thus avoiding having to
   * create entry objects in next().
   */
  abstract class EntryIter extends Iter implements Map.Entry<K, V> {
    /** Cache of last value returned */
    Object lastValue;

    EntryIter() {
    }

    public K getKey() {
      Node<K, V> l = last;
      if (l == null)
        throw new IllegalStateException();
      return l.key;
    }

    public V getValue() {
      Object v = lastValue;
      if (last == null || v == null)
        throw new IllegalStateException();
      return (V) v;
    }

    public V setValue(V value) {
      throw new UnsupportedOperationException();
    }

    public boolean equals(Object o) {
      // If not acting as entry, just use default.
      if (last == null)
        return super.equals(o);
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry e = (Map.Entry) o;
      return (getKey().equals(e.getKey()) && getValue().equals(e.getValue()));
    }

    public int hashCode() {
      // If not acting as entry, just use default.
      if (last == null)
        return super.hashCode();
      return getKey().hashCode() ^ getValue().hashCode();
    }

    public String toString() {
      // If not acting as entry, just use default.
      if (last == null)
        return super.toString();
      return getKey() + "=" + getValue();
    }
  }

  final class EntryIterator extends EntryIter implements Iterator<Map.Entry<K, V>> {
    EntryIterator() {
      initAscending();
    }

    public Map.Entry<K, V> next() {
      lastValue = nextValue;
      ascend();
      return this;
    }
  }

  final class SubMapEntryIterator extends EntryIter implements Iterator<Map.Entry<K, V>> {
    final K fence;

    SubMapEntryIterator(K least, K fence) {
      initAscending(least, fence);
      this.fence = fence;
    }

    public Map.Entry<K, V> next() {
      lastValue = nextValue;
      ascend(fence);
      return this;
    }
  }

  final class DescendingEntryIterator extends EntryIter implements Iterator<Map.Entry<K, V>> {
    DescendingEntryIterator() {
      initDescending();
    }

    public Map.Entry<K, V> next() {
      lastValue = nextValue;
      descend();
      return this;
    }
  }

  final class DescendingSubMapEntryIterator extends EntryIter implements Iterator<Map.Entry<K, V>> {
    final K least;

    DescendingSubMapEntryIterator(K least, K fence) {
      initDescending(least, fence);
      this.least = least;
    }

    public Map.Entry<K, V> next() {
      lastValue = nextValue;
      descend(least);
      return this;
    }
  }

  // Factory methods for iterators needed by submaps and/or
  // ConcurrentSkipListSet

  Iterator<K> keyIterator() {
    return new KeyIterator();
  }

  Iterator<K> descendingKeyIterator() {
    return new DescendingKeyIterator();
  }

  SubMapEntryIterator subMapEntryIterator(K least, K fence) {
    return new SubMapEntryIterator(least, fence);
  }

  DescendingSubMapEntryIterator descendingSubMapEntryIterator(K least, K fence) {
    return new DescendingSubMapEntryIterator(least, fence);
  }

  SubMapKeyIterator subMapKeyIterator(K least, K fence) {
    return new SubMapKeyIterator(least, fence);
  }

  DescendingSubMapKeyIterator descendingSubMapKeyIterator(K least, K fence) {
    return new DescendingSubMapKeyIterator(least, fence);
  }

  SubMapValueIterator subMapValueIterator(K least, K fence) {
    return new SubMapValueIterator(least, fence);
  }

  /* ---------------- Views -------------- */

  class KeySet extends AbstractSet<K> {
    public Iterator<K> iterator() {
      return new KeyIterator();
    }

    public boolean isEmpty() {
      return ConcurrentSkipListMap.this.isEmpty();
    }

    public int size() {
      return ConcurrentSkipListMap.this.size();
    }

    public boolean contains(Object o) {
      return ConcurrentSkipListMap.this.containsKey(o);
    }

    public boolean remove(Object o) {
      return ConcurrentSkipListMap.this.removep(o);
    }

    public void clear() {
      ConcurrentSkipListMap.this.clear();
    }

    public Object[] toArray() {
      Collection<K> c = new ArrayList<K>();
      for (Iterator<K> i = iterator(); i.hasNext();)
        c.add(i.next());
      return c.toArray();
    }

    public <T> T[] toArray(T[] a) {
      Collection<K> c = new ArrayList<K>();
      for (Iterator<K> i = iterator(); i.hasNext();)
        c.add(i.next());
      return c.toArray(a);
    }
  }

  class DescendingKeySet extends KeySet {
    public Iterator<K> iterator() {
      return new DescendingKeyIterator();
    }
  }

  final class Values extends AbstractCollection<V> {
    public Iterator<V> iterator() {
      return new ValueIterator();
    }

    public boolean isEmpty() {
      return ConcurrentSkipListMap.this.isEmpty();
    }

    public int size() {
      return ConcurrentSkipListMap.this.size();
    }

    public boolean contains(Object o) {
      return ConcurrentSkipListMap.this.containsValue(o);
    }

    public void clear() {
      ConcurrentSkipListMap.this.clear();
    }

    public Object[] toArray() {
      Collection<V> c = new ArrayList<V>();
      for (Iterator<V> i = iterator(); i.hasNext();)
        c.add(i.next());
      return c.toArray();
    }

    public <T> T[] toArray(T[] a) {
      Collection<V> c = new ArrayList<V>();
      for (Iterator<V> i = iterator(); i.hasNext();)
        c.add(i.next());
      return c.toArray(a);
    }
  }

  class EntrySet extends AbstractSet<Map.Entry<K, V>> {
    public Iterator<Map.Entry<K, V>> iterator() {
      return new EntryIterator();
    }

    public boolean contains(Object o) {
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry<K, V> e = (Map.Entry<K, V>) o;
      V v = ConcurrentSkipListMap.this.get(e.getKey());
      return v != null && v.equals(e.getValue());
    }

    public boolean remove(Object o) {
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry<K, V> e = (Map.Entry<K, V>) o;
      return ConcurrentSkipListMap.this.remove(e.getKey(), e.getValue());
    }

    public boolean isEmpty() {
      return ConcurrentSkipListMap.this.isEmpty();
    }

    public int size() {
      return ConcurrentSkipListMap.this.size();
    }

    public void clear() {
      ConcurrentSkipListMap.this.clear();
    }

    public Object[] toArray() {
      Collection<Map.Entry<K, V>> c = new ArrayList<Map.Entry<K, V>>();
      for (Map.Entry e : this)
        c.add(new SnapshotEntry(e.getKey(), e.getValue()));
      return c.toArray();
    }

    public <T> T[] toArray(T[] a) {
      Collection<Map.Entry<K, V>> c = new ArrayList<Map.Entry<K, V>>();
      for (Map.Entry e : this)
        c.add(new SnapshotEntry(e.getKey(), e.getValue()));
      return c.toArray(a);
    }
  }

  class DescendingEntrySet extends EntrySet {
    public Iterator<Map.Entry<K, V>> iterator() {
      return new DescendingEntryIterator();
    }
  }

  /**
   * Submaps returned by {@link ConcurrentSkipListMap} submap operations
   * represent a subrange of mappings of their underlying maps. Instances of
   * this class support all methods of their underlying maps, differing in that
   * mappings outside their range are ignored, and attempts to add mappings
   * outside their ranges result in {@link IllegalArgumentException}. Instances
   * of this class are constructed only using the <tt>subMap</tt>,
   * <tt>headMap</tt>, and <tt>tailMap</tt> methods of their underlying
   * maps.
   */
  static class ConcurrentSkipListSubMap<K, V> extends AbstractMap<K, V> implements
      ConcurrentNavigableMap<K, V>, java.io.Serializable {

    private static final long serialVersionUID = -7647078645895051609L;

    /** Underlying map */
    private final ConcurrentSkipListMap<K, V> m;

    /** lower bound key, or null if from start */
    private final K least;

    /** upper fence key, or null if to end */
    private final K fence;

    // Lazily initialized view holders
    private transient Set<K> keySetView;

    private transient Set<Map.Entry<K, V>> entrySetView;

    private transient Collection<V> valuesView;

    private transient Set<K> descendingKeySetView;

    private transient Set<Map.Entry<K, V>> descendingEntrySetView;

    /**
     * Creates a new submap.
     * 
     * @param least
     *          inclusive least value, or <tt>null</tt> if from start
     * @param fence
     *          exclusive upper bound or <tt>null</tt> if to end
     * @throws IllegalArgumentException
     *           if least and fence nonnull and least greater than fence
     */
    ConcurrentSkipListSubMap(ConcurrentSkipListMap<K, V> map, K least, K fence) {
      if (least != null && fence != null && map.compare(least, fence) > 0)
        throw new IllegalArgumentException("inconsistent range");
      this.m = map;
      this.least = least;
      this.fence = fence;
    }

    /* ---------------- Utilities -------------- */

    boolean inHalfOpenRange(K key) {
      return m.inHalfOpenRange(key, least, fence);
    }

    boolean inOpenRange(K key) {
      return m.inOpenRange(key, least, fence);
    }

    ConcurrentSkipListMap.Node<K, V> firstNode() {
      return m.findCeiling(least);
    }

    ConcurrentSkipListMap.Node<K, V> lastNode() {
      return m.findLower(fence);
    }

    boolean isBeforeEnd(ConcurrentSkipListMap.Node<K, V> n) {
      return (n != null && (fence == null || n.key == null || // pass by markers
                                                              // and headers
      m.compare(fence, n.key) > 0));
    }

    void checkKey(K key) throws IllegalArgumentException {
      if (!inHalfOpenRange(key))
        throw new IllegalArgumentException("key out of range");
    }

    /**
     * Returns underlying map. Needed by ConcurrentSkipListSet
     * 
     * @return the backing map
     */
    ConcurrentSkipListMap<K, V> getMap() {
      return m;
    }

    /**
     * Returns least key. Needed by ConcurrentSkipListSet
     * 
     * @return least key or <tt>null</tt> if from start
     */
    K getLeast() {
      return least;
    }

    /**
     * Returns fence key. Needed by ConcurrentSkipListSet
     * 
     * @return fence key or <tt>null</tt> of to end
     */
    K getFence() {
      return fence;
    }

    /* ---------------- Map API methods -------------- */

    public boolean containsKey(Object key) {
      K k = (K) key;
      return inHalfOpenRange(k) && m.containsKey(k);
    }

    public V get(Object key) {
      K k = (K) key;
      return ((!inHalfOpenRange(k)) ? null : m.get(k));
    }

    public V put(K key, V value) {
      checkKey(key);
      return m.put(key, value);
    }

    public V remove(Object key) {
      K k = (K) key;
      return (!inHalfOpenRange(k)) ? null : m.remove(k);
    }

    public int size() {
      long count = 0;
      for (ConcurrentSkipListMap.Node<K, V> n = firstNode(); isBeforeEnd(n); n = n.next) {
        if (n.getValidValue() != null)
          ++count;
      }
      return count >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) count;
    }

    public boolean isEmpty() {
      return !isBeforeEnd(firstNode());
    }

    public boolean containsValue(Object value) {
      if (value == null)
        throw new NullPointerException();
      for (ConcurrentSkipListMap.Node<K, V> n = firstNode(); isBeforeEnd(n); n = n.next) {
        V v = n.getValidValue();
        if (v != null && value.equals(v))
          return true;
      }
      return false;
    }

    public void clear() {
      for (ConcurrentSkipListMap.Node<K, V> n = firstNode(); isBeforeEnd(n); n = n.next) {
        if (n.getValidValue() != null)
          m.remove(n.key);
      }
    }

    /* ---------------- ConcurrentMap API methods -------------- */

    public V putIfAbsent(K key, V value) {
      checkKey(key);
      return m.putIfAbsent(key, value);
    }

    public boolean remove(Object key, Object value) {
      K k = (K) key;
      return inHalfOpenRange(k) && m.remove(k, value);
    }

    public boolean replace(K key, V oldValue, V newValue) {
      checkKey(key);
      return m.replace(key, oldValue, newValue);
    }

    public V replace(K key, V value) {
      checkKey(key);
      return m.replace(key, value);
    }

    /* ---------------- SortedMap API methods -------------- */

    public Comparator<? super K> comparator() {
      return m.comparator();
    }

    public K firstKey() {
      ConcurrentSkipListMap.Node<K, V> n = firstNode();
      if (isBeforeEnd(n))
        return n.key;
      else
        throw new NoSuchElementException();
    }

    public K lastKey() {
      ConcurrentSkipListMap.Node<K, V> n = lastNode();
      if (n != null) {
        K last = n.key;
        if (inHalfOpenRange(last))
          return last;
      }
      throw new NoSuchElementException();
    }

    public ConcurrentNavigableMap<K, V> subMap(K fromKey, K toKey) {
      if (fromKey == null || toKey == null)
        throw new NullPointerException();
      if (!inOpenRange(fromKey) || !inOpenRange(toKey))
        throw new IllegalArgumentException("key out of range");
      return new ConcurrentSkipListSubMap(m, fromKey, toKey);
    }

    public ConcurrentNavigableMap<K, V> headMap(K toKey) {
      if (toKey == null)
        throw new NullPointerException();
      if (!inOpenRange(toKey))
        throw new IllegalArgumentException("key out of range");
      return new ConcurrentSkipListSubMap(m, least, toKey);
    }

    public ConcurrentNavigableMap<K, V> tailMap(K fromKey) {
      if (fromKey == null)
        throw new NullPointerException();
      if (!inOpenRange(fromKey))
        throw new IllegalArgumentException("key out of range");
      return new ConcurrentSkipListSubMap(m, fromKey, fence);
    }

    /* ---------------- Relational methods -------------- */

    public Map.Entry<K, V> ceilingEntry(K key) {
      return (SnapshotEntry<K, V>) m.getNear(key, m.GT | m.EQ, least, fence, false);
    }

    public K ceilingKey(K key) {
      return (K) m.getNear(key, m.GT | m.EQ, least, fence, true);
    }

    public Map.Entry<K, V> lowerEntry(K key) {
      return (SnapshotEntry<K, V>) m.getNear(key, m.LT, least, fence, false);
    }

    public K lowerKey(K key) {
      return (K) m.getNear(key, m.LT, least, fence, true);
    }

    public Map.Entry<K, V> floorEntry(K key) {
      return (SnapshotEntry<K, V>) m.getNear(key, m.LT | m.EQ, least, fence, false);
    }

    public K floorKey(K key) {
      return (K) m.getNear(key, m.LT | m.EQ, least, fence, true);
    }

    public Map.Entry<K, V> higherEntry(K key) {
      return (SnapshotEntry<K, V>) m.getNear(key, m.GT, least, fence, false);
    }

    public K higherKey(K key) {
      return (K) m.getNear(key, m.GT, least, fence, true);
    }

    public Map.Entry<K, V> firstEntry() {
      for (;;) {
        ConcurrentSkipListMap.Node<K, V> n = firstNode();
        if (!isBeforeEnd(n))
          return null;
        Map.Entry<K, V> e = n.createSnapshot();
        if (e != null)
          return e;
      }
    }

    public Map.Entry<K, V> lastEntry() {
      for (;;) {
        ConcurrentSkipListMap.Node<K, V> n = lastNode();
        if (n == null || !inHalfOpenRange(n.key))
          return null;
        Map.Entry<K, V> e = n.createSnapshot();
        if (e != null)
          return e;
      }
    }

    public Map.Entry<K, V> pollFirstEntry() {
      return (SnapshotEntry<K, V>) m.removeFirstEntryOfSubrange(least, fence, false);
    }

    public Map.Entry<K, V> pollLastEntry() {
      return (SnapshotEntry<K, V>) m.removeLastEntryOfSubrange(least, fence, false);
    }

    /* ---------------- Submap Views -------------- */

    public Set<K> keySet() {
      Set<K> ks = keySetView;
      return (ks != null) ? ks : (keySetView = new KeySetView());
    }

    class KeySetView extends AbstractSet<K> {
      public Iterator<K> iterator() {
        return m.subMapKeyIterator(least, fence);
      }

      public int size() {
        return ConcurrentSkipListSubMap.this.size();
      }

      public boolean isEmpty() {
        return ConcurrentSkipListSubMap.this.isEmpty();
      }

      public boolean contains(Object k) {
        return ConcurrentSkipListSubMap.this.containsKey(k);
      }

      public Object[] toArray() {
        Collection<K> c = new ArrayList<K>();
        for (Iterator<K> i = iterator(); i.hasNext();)
          c.add(i.next());
        return c.toArray();
      }

      public <T> T[] toArray(T[] a) {
        Collection<K> c = new ArrayList<K>();
        for (Iterator<K> i = iterator(); i.hasNext();)
          c.add(i.next());
        return c.toArray(a);
      }
    }

    public Set<K> descendingKeySet() {
      Set<K> ks = descendingKeySetView;
      return (ks != null) ? ks : (descendingKeySetView = new DescendingKeySetView());
    }

    class DescendingKeySetView extends KeySetView {
      public Iterator<K> iterator() {
        return m.descendingSubMapKeyIterator(least, fence);
      }
    }

    public Collection<V> values() {
      Collection<V> vs = valuesView;
      return (vs != null) ? vs : (valuesView = new ValuesView());
    }

    class ValuesView extends AbstractCollection<V> {
      public Iterator<V> iterator() {
        return m.subMapValueIterator(least, fence);
      }

      public int size() {
        return ConcurrentSkipListSubMap.this.size();
      }

      public boolean isEmpty() {
        return ConcurrentSkipListSubMap.this.isEmpty();
      }

      public boolean contains(Object v) {
        return ConcurrentSkipListSubMap.this.containsValue(v);
      }

      public Object[] toArray() {
        Collection<V> c = new ArrayList<V>();
        for (Iterator<V> i = iterator(); i.hasNext();)
          c.add(i.next());
        return c.toArray();
      }

      public <T> T[] toArray(T[] a) {
        Collection<V> c = new ArrayList<V>();
        for (Iterator<V> i = iterator(); i.hasNext();)
          c.add(i.next());
        return c.toArray(a);
      }
    }

    public Set<Map.Entry<K, V>> entrySet() {
      Set<Map.Entry<K, V>> es = entrySetView;
      return (es != null) ? es : (entrySetView = new EntrySetView());
    }

    class EntrySetView extends AbstractSet<Map.Entry<K, V>> {
      public Iterator<Map.Entry<K, V>> iterator() {
        return m.subMapEntryIterator(least, fence);
      }

      public int size() {
        return ConcurrentSkipListSubMap.this.size();
      }

      public boolean isEmpty() {
        return ConcurrentSkipListSubMap.this.isEmpty();
      }

      public boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
          return false;
        Map.Entry<K, V> e = (Map.Entry<K, V>) o;
        K key = e.getKey();
        if (!inHalfOpenRange(key))
          return false;
        V v = m.get(key);
        return v != null && v.equals(e.getValue());
      }

      public boolean remove(Object o) {
        if (!(o instanceof Map.Entry))
          return false;
        Map.Entry<K, V> e = (Map.Entry<K, V>) o;
        K key = e.getKey();
        if (!inHalfOpenRange(key))
          return false;
        return m.remove(key, e.getValue());
      }

      public Object[] toArray() {
        Collection<Map.Entry<K, V>> c = new ArrayList<Map.Entry<K, V>>();
        for (Map.Entry e : this)
          c.add(new SnapshotEntry(e.getKey(), e.getValue()));
        return c.toArray();
      }

      public <T> T[] toArray(T[] a) {
        Collection<Map.Entry<K, V>> c = new ArrayList<Map.Entry<K, V>>();
        for (Map.Entry e : this)
          c.add(new SnapshotEntry(e.getKey(), e.getValue()));
        return c.toArray(a);
      }
    }

    public Set<Map.Entry<K, V>> descendingEntrySet() {
      Set<Map.Entry<K, V>> es = descendingEntrySetView;
      return (es != null) ? es : (descendingEntrySetView = new DescendingEntrySetView());
    }

    class DescendingEntrySetView extends EntrySetView {
      public Iterator<Map.Entry<K, V>> iterator() {
        return m.descendingSubMapEntryIterator(least, fence);
      }
    }
  }
}

   
    
    
    
  








Related examples in the same category

1.Ordered Map
2.Case Insensitive Map
3.A Map collection with real-time behavior
4.Cache Map
5.Map implementation Optimized for Strings keys
6.An integer hashmap
7.An IdentityMap that uses reference-equality instead of object-equality
8.Int Object HashMap
9.A hash map that uses primitive ints for the key rather than objects.
10.Integer Map
11.Copy On Write Map
12.Expiring Map
13.Array Map
14.Int Object HashMap (from CERN)
15.Int HashMap from jodd.org
16.String Map
17.List Map
18.Map using Locale objects as keys
19.Map with keys iterated in insertion order
20.Most Recently Used Map
21.Multi Map
22.MultiMap is a Java version of the C++ STL class std::multimap
23.Object Int Map
24.Sequenced HashMap
25.Int Int Map
26.Int Object Map
27.Identity HashMap
28.A java.util.Map interface which can only hold a single object
29.A multi valued Map
30.A simple hashmap from keys to integers
31.A memory-efficient hash map.
32.An implementation of the java.util.Map interface which can only hold a single object.
33.Utility methods for operating on memory-efficient maps.
34.CaseBlindHashMap - a HashMap extension, using Strings as key values.
35.A fixed size map implementation.
36.Int HashMap
37.IntMap provides a simple hashmap from keys to integers
38.Complex Key HashMap
39.A Map with multiple values for a key
40.A Map that accepts int or Integer keys only
41.A Map where keys are compared by object identity, rather than equals()
42.Type-safe Map, from char array to String value
43.A hashtable-based Map implementation with soft keys
44.List ordered map
45.Hash map using String values as keys mapped to primitive int values.
46.Lookup table that stores a list of strings
47.HashNMap stores multiple values by a single key value. Values can be retrieved using a direct query or by creating an enumeration over the stored elements.
48.Combines multiple values to form a single composite key. MultiKey can often be used as an alternative to nested maps.