8011427: java.util.concurrent collection Spliterator implementations
authorpsandoz
Wed, 03 Jul 2013 11:58:09 +0200
changeset 18767 6214297bf27d
parent 18766 28c62f5e9a47
child 18768 f2638f396c41
8011427: java.util.concurrent collection Spliterator implementations Reviewed-by: martin Contributed-by: Doug Lea <dl@cs.oswego.edu>
jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java
jdk/src/share/classes/java/util/concurrent/BlockingDeque.java
jdk/src/share/classes/java/util/concurrent/BlockingQueue.java
jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
jdk/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java
jdk/src/share/classes/java/util/concurrent/DelayQueue.java
jdk/src/share/classes/java/util/concurrent/Delayed.java
jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java
jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java
jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java
jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java
jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java
--- a/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -34,8 +34,15 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
-import java.util.*;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.lang.ref.WeakReference;
+import java.util.Spliterators;
+import java.util.Spliterator;
 
 /**
  * A bounded {@linkplain BlockingQueue blocking queue} backed by an
@@ -102,19 +109,21 @@
 
     /** Main lock guarding all access */
     final ReentrantLock lock;
+
     /** Condition for waiting takes */
     private final Condition notEmpty;
+
     /** Condition for waiting puts */
     private final Condition notFull;
 
-    // Internal helper methods
+    /**
+     * Shared state for currently active iterators, or null if there
+     * are known not to be any.  Allows queue operations to update
+     * iterator state.
+     */
+    transient Itrs itrs = null;
 
-    /**
-     * Circularly increment i.
-     */
-    final int inc(int i) {
-        return (++i == items.length) ? 0 : i;
-    }
+    // Internal helper methods
 
     /**
      * Circularly decrement i.
@@ -123,11 +132,6 @@
         return ((i == 0) ? items.length : i) - 1;
     }
 
-    @SuppressWarnings("unchecked")
-    static <E> E cast(Object item) {
-        return (E) item;
-    }
-
     /**
      * Returns item at index i.
      */
@@ -150,10 +154,14 @@
      * Inserts element at current put position, advances, and signals.
      * Call only when holding lock.
      */
-    private void insert(E x) {
+    private void enqueue(E x) {
+        // assert lock.getHoldCount() == 1;
+        // assert items[putIndex] == null;
+        final Object[] items = this.items;
         items[putIndex] = x;
-        putIndex = inc(putIndex);
-        ++count;
+        if (++putIndex == items.length)
+            putIndex = 0;
+        count++;
         notEmpty.signal();
     }
 
@@ -161,43 +169,62 @@
      * Extracts element at current take position, advances, and signals.
      * Call only when holding lock.
      */
-    private E extract() {
+    private E dequeue() {
+        // assert lock.getHoldCount() == 1;
+        // assert items[takeIndex] != null;
         final Object[] items = this.items;
         @SuppressWarnings("unchecked")
         E x = (E) items[takeIndex];
         items[takeIndex] = null;
-        takeIndex = inc(takeIndex);
-        --count;
+        if (++takeIndex == items.length)
+            takeIndex = 0;
+        count--;
+        if (itrs != null)
+            itrs.elementDequeued();
         notFull.signal();
         return x;
     }
 
     /**
-     * Deletes item at position i.
-     * Utility for remove and iterator.remove.
+     * Deletes item at array index removeIndex.
+     * Utility for remove(Object) and iterator.remove.
      * Call only when holding lock.
      */
-    void removeAt(int i) {
+    void removeAt(final int removeIndex) {
+        // assert lock.getHoldCount() == 1;
+        // assert items[removeIndex] != null;
+        // assert removeIndex >= 0 && removeIndex < items.length;
         final Object[] items = this.items;
-        // if removing front item, just advance
-        if (i == takeIndex) {
+        if (removeIndex == takeIndex) {
+            // removing front item; just advance
             items[takeIndex] = null;
-            takeIndex = inc(takeIndex);
+            if (++takeIndex == items.length)
+                takeIndex = 0;
+            count--;
+            if (itrs != null)
+                itrs.elementDequeued();
         } else {
+            // an "interior" remove
+
             // slide over all others up through putIndex.
-            for (;;) {
-                int nexti = inc(i);
-                if (nexti != putIndex) {
-                    items[i] = items[nexti];
-                    i = nexti;
+            final int putIndex = this.putIndex;
+            for (int i = removeIndex;;) {
+                int next = i + 1;
+                if (next == items.length)
+                    next = 0;
+                if (next != putIndex) {
+                    items[i] = items[next];
+                    i = next;
                 } else {
                     items[i] = null;
-                    putIndex = i;
+                    this.putIndex = i;
                     break;
                 }
             }
+            count--;
+            if (itrs != null)
+                itrs.removedAt(removeIndex);
         }
-        --count;
         notFull.signal();
     }
 
@@ -302,7 +329,7 @@
             if (count == items.length)
                 return false;
             else {
-                insert(e);
+                enqueue(e);
                 return true;
             }
         } finally {
@@ -324,7 +351,7 @@
         try {
             while (count == items.length)
                 notFull.await();
-            insert(e);
+            enqueue(e);
         } finally {
             lock.unlock();
         }
@@ -351,7 +378,7 @@
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
-            insert(e);
+            enqueue(e);
             return true;
         } finally {
             lock.unlock();
@@ -362,7 +389,7 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return (count == 0) ? null : extract();
+            return (count == 0) ? null : dequeue();
         } finally {
             lock.unlock();
         }
@@ -374,7 +401,7 @@
         try {
             while (count == 0)
                 notEmpty.await();
-            return extract();
+            return dequeue();
         } finally {
             lock.unlock();
         }
@@ -390,7 +417,7 @@
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
-            return extract();
+            return dequeue();
         } finally {
             lock.unlock();
         }
@@ -400,7 +427,7 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return (count == 0) ? null : itemAt(takeIndex);
+            return itemAt(takeIndex); // null when queue is empty
         } finally {
             lock.unlock();
         }
@@ -469,11 +496,17 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) {
-                if (o.equals(items[i])) {
-                    removeAt(i);
-                    return true;
-                }
+            if (count > 0) {
+                final int putIndex = this.putIndex;
+                int i = takeIndex;
+                do {
+                    if (o.equals(items[i])) {
+                        removeAt(i);
+                        return true;
+                    }
+                    if (++i == items.length)
+                        i = 0;
+                } while (i != putIndex);
             }
             return false;
         } finally {
@@ -495,9 +528,16 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
-                if (o.equals(items[i]))
-                    return true;
+            if (count > 0) {
+                final int putIndex = this.putIndex;
+                int i = takeIndex;
+                do {
+                    if (o.equals(items[i]))
+                        return true;
+                    if (++i == items.length)
+                        i = 0;
+                } while (i != putIndex);
+            }
             return false;
         } finally {
             lock.unlock();
@@ -518,18 +558,23 @@
      * @return an array containing all of the elements in this queue
      */
     public Object[] toArray() {
-        final Object[] items = this.items;
+        Object[] a;
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             final int count = this.count;
-            Object[] a = new Object[count];
-            for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
-                a[k] = items[i];
-            return a;
+            a = new Object[count];
+            int n = items.length - takeIndex;
+            if (count <= n)
+                System.arraycopy(items, takeIndex, a, 0, count);
+            else {
+                System.arraycopy(items, takeIndex, a, 0, n);
+                System.arraycopy(items, 0, a, n, count - n);
+            }
         } finally {
             lock.unlock();
         }
+        return a;
     }
 
     /**
@@ -553,8 +598,7 @@
      * The following code can be used to dump the queue into a newly
      * allocated array of {@code String}:
      *
-     * <pre>
-     *     String[] y = x.toArray(new String[0]);</pre>
+     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
      * Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
@@ -579,14 +623,19 @@
             if (len < count)
                 a = (T[])java.lang.reflect.Array.newInstance(
                     a.getClass().getComponentType(), count);
-            for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
-                a[k] = (T) items[i];
+            int n = items.length - takeIndex;
+            if (count <= n)
+                System.arraycopy(items, takeIndex, a, 0, count);
+            else {
+                System.arraycopy(items, takeIndex, a, 0, n);
+                System.arraycopy(items, 0, a, n, count - n);
+            }
             if (len > count)
                 a[count] = null;
-            return a;
         } finally {
             lock.unlock();
         }
+        return a;
     }
 
     public String toString() {
@@ -597,14 +646,17 @@
             if (k == 0)
                 return "[]";
 
+            final Object[] items = this.items;
             StringBuilder sb = new StringBuilder();
             sb.append('[');
-            for (int i = takeIndex; ; i = inc(i)) {
+            for (int i = takeIndex; ; ) {
                 Object e = items[i];
                 sb.append(e == this ? "(this Collection)" : e);
                 if (--k == 0)
                     return sb.append(']').toString();
                 sb.append(',').append(' ');
+                if (++i == items.length)
+                    i = 0;
             }
         } finally {
             lock.unlock();
@@ -620,12 +672,22 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
-                items[i] = null;
-            count = 0;
-            putIndex = 0;
-            takeIndex = 0;
-            notFull.signalAll();
+            int k = count;
+            if (k > 0) {
+                final int putIndex = this.putIndex;
+                int i = takeIndex;
+                do {
+                    items[i] = null;
+                    if (++i == items.length)
+                        i = 0;
+                } while (i != putIndex);
+                takeIndex = putIndex;
+                count = 0;
+                if (itrs != null)
+                    itrs.queueIsEmpty();
+                for (; k > 0 && lock.hasWaiters(notFull); k--)
+                    notFull.signal();
+            }
         } finally {
             lock.unlock();
         }
@@ -638,34 +700,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        checkNotNull(c);
-        if (c == this)
-            throw new IllegalArgumentException();
-        final Object[] items = this.items;
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            int i = takeIndex;
-            int n = 0;
-            int max = count;
-            while (n < max) {
-                @SuppressWarnings("unchecked")
-                E x = (E) items[i];
-                c.add(x);
-                items[i] = null;
-                i = inc(i);
-                ++n;
-            }
-            if (n > 0) {
-                count = 0;
-                putIndex = 0;
-                takeIndex = 0;
-                notFull.signalAll();
-            }
-            return n;
-        } finally {
-            lock.unlock();
-        }
+        return drainTo(c, Integer.MAX_VALUE);
     }
 
     /**
@@ -684,23 +719,35 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int i = takeIndex;
-            int n = 0;
-            int max = (maxElements < count) ? maxElements : count;
-            while (n < max) {
-                @SuppressWarnings("unchecked")
-                E x = (E) items[i];
-                c.add(x);
-                items[i] = null;
-                i = inc(i);
-                ++n;
+            int n = Math.min(maxElements, count);
+            int take = takeIndex;
+            int i = 0;
+            try {
+                while (i < n) {
+                    @SuppressWarnings("unchecked")
+                    E x = (E) items[take];
+                    c.add(x);
+                    items[take] = null;
+                    if (++take == items.length)
+                        take = 0;
+                    i++;
+                }
+                return n;
+            } finally {
+                // Restore invariants even if c.add() threw
+                if (i > 0) {
+                    count -= i;
+                    takeIndex = take;
+                    if (itrs != null) {
+                        if (count == 0)
+                            itrs.queueIsEmpty();
+                        else if (i > take)
+                            itrs.takeIndexWrapped();
+                    }
+                    for (; i > 0 && lock.hasWaiters(notFull); i--)
+                        notFull.signal();
+                }
             }
-            if (n > 0) {
-                count -= n;
-                takeIndex = i;
-                notFull.signalAll();
-            }
-            return n;
         } finally {
             lock.unlock();
         }
@@ -710,12 +757,12 @@
      * Returns an iterator over the elements in this queue in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
-     * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
+     * <p>The returned iterator is a "weakly consistent" iterator that
      * will never throw {@link java.util.ConcurrentModificationException
-     * 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.
+     * 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 an iterator over the elements in this queue in proper sequence
      */
@@ -724,88 +771,634 @@
     }
 
     /**
-     * Iterator for ArrayBlockingQueue. To maintain weak consistency
-     * with respect to puts and takes, we (1) read ahead one slot, so
-     * as to not report hasNext true but then not have an element to
-     * return -- however we later recheck this slot to use the most
-     * current value; (2) ensure that each array slot is traversed at
-     * most once (by tracking "remaining" elements); (3) skip over
-     * null slots, which can occur if takes race ahead of iterators.
-     * However, for circular array-based queues, we cannot rely on any
-     * well established definition of what it means to be weakly
-     * consistent with respect to interior removes since these may
-     * require slot overwrites in the process of sliding elements to
-     * cover gaps. So we settle for resiliency, operating on
-     * established apparent nexts, which may miss some elements that
-     * have moved between calls to next.
+     * Shared data between iterators and their queue, allowing queue
+     * modifications to update iterators when elements are removed.
+     *
+     * This adds a lot of complexity for the sake of correctly
+     * handling some uncommon operations, but the combination of
+     * circular-arrays and supporting interior removes (i.e., those
+     * not at head) would cause iterators to sometimes lose their
+     * places and/or (re)report elements they shouldn't.  To avoid
+     * this, when a queue has one or more iterators, it keeps iterator
+     * state consistent by:
+     *
+     * (1) keeping track of the number of "cycles", that is, the
+     *     number of times takeIndex has wrapped around to 0.
+     * (2) notifying all iterators via the callback removedAt whenever
+     *     an interior element is removed (and thus other elements may
+     *     be shifted).
+     *
+     * These suffice to eliminate iterator inconsistencies, but
+     * unfortunately add the secondary responsibility of maintaining
+     * the list of iterators.  We track all active iterators in a
+     * simple linked list (accessed only when the queue's lock is
+     * held) of weak references to Itr.  The list is cleaned up using
+     * 3 different mechanisms:
+     *
+     * (1) Whenever a new iterator is created, do some O(1) checking for
+     *     stale list elements.
+     *
+     * (2) Whenever takeIndex wraps around to 0, check for iterators
+     *     that have been unused for more than one wrap-around cycle.
+     *
+     * (3) Whenever the queue becomes empty, all iterators are notified
+     *     and this entire data structure is discarded.
+     *
+     * So in addition to the removedAt callback that is necessary for
+     * correctness, iterators have the shutdown and takeIndexWrapped
+     * callbacks that help remove stale iterators from the list.
+     *
+     * Whenever a list element is examined, it is expunged if either
+     * the GC has determined that the iterator is discarded, or if the
+     * iterator reports that it is "detached" (does not need any
+     * further state updates).  Overhead is maximal when takeIndex
+     * never advances, iterators are discarded before they are
+     * exhausted, and all removals are interior removes, in which case
+     * all stale iterators are discovered by the GC.  But even in this
+     * case we don't increase the amortized complexity.
+     *
+     * Care must be taken to keep list sweeping methods from
+     * reentrantly invoking another such method, causing subtle
+     * corruption bugs.
+     */
+    class Itrs {
+
+        /**
+         * Node in a linked list of weak iterator references.
+         */
+        private class Node extends WeakReference<Itr> {
+            Node next;
+
+            Node(Itr iterator, Node next) {
+                super(iterator);
+                this.next = next;
+            }
+        }
+
+        /** Incremented whenever takeIndex wraps around to 0 */
+        int cycles = 0;
+
+        /** Linked list of weak iterator references */
+        private Node head;
+
+        /** Used to expunge stale iterators */
+        private Node sweeper = null;
+
+        private static final int SHORT_SWEEP_PROBES = 4;
+        private static final int LONG_SWEEP_PROBES = 16;
+
+        Itrs(Itr initial) {
+            register(initial);
+        }
+
+        /**
+         * Sweeps itrs, looking for and expunging stale iterators.
+         * If at least one was found, tries harder to find more.
+         * Called only from iterating thread.
+         *
+         * @param tryHarder whether to start in try-harder mode, because
+         * there is known to be at least one iterator to collect
+         */
+        void doSomeSweeping(boolean tryHarder) {
+            // assert lock.getHoldCount() == 1;
+            // assert head != null;
+            int probes = tryHarder ? LONG_SWEEP_PROBES : SHORT_SWEEP_PROBES;
+            Node o, p;
+            final Node sweeper = this.sweeper;
+            boolean passedGo;   // to limit search to one full sweep
+
+            if (sweeper == null) {
+                o = null;
+                p = head;
+                passedGo = true;
+            } else {
+                o = sweeper;
+                p = o.next;
+                passedGo = false;
+            }
+
+            for (; probes > 0; probes--) {
+                if (p == null) {
+                    if (passedGo)
+                        break;
+                    o = null;
+                    p = head;
+                    passedGo = true;
+                }
+                final Itr it = p.get();
+                final Node next = p.next;
+                if (it == null || it.isDetached()) {
+                    // found a discarded/exhausted iterator
+                    probes = LONG_SWEEP_PROBES; // "try harder"
+                    // unlink p
+                    p.clear();
+                    p.next = null;
+                    if (o == null) {
+                        head = next;
+                        if (next == null) {
+                            // We've run out of iterators to track; retire
+                            itrs = null;
+                            return;
+                        }
+                    }
+                    else
+                        o.next = next;
+                } else {
+                    o = p;
+                }
+                p = next;
+            }
+
+            this.sweeper = (p == null) ? null : o;
+        }
+
+        /**
+         * Adds a new iterator to the linked list of tracked iterators.
+         */
+        void register(Itr itr) {
+            // assert lock.getHoldCount() == 1;
+            head = new Node(itr, head);
+        }
+
+        /**
+         * Called whenever takeIndex wraps around to 0.
+         *
+         * Notifies all iterators, and expunges any that are now stale.
+         */
+        void takeIndexWrapped() {
+            // assert lock.getHoldCount() == 1;
+            cycles++;
+            for (Node o = null, p = head; p != null;) {
+                final Itr it = p.get();
+                final Node next = p.next;
+                if (it == null || it.takeIndexWrapped()) {
+                    // unlink p
+                    // assert it == null || it.isDetached();
+                    p.clear();
+                    p.next = null;
+                    if (o == null)
+                        head = next;
+                    else
+                        o.next = next;
+                } else {
+                    o = p;
+                }
+                p = next;
+            }
+            if (head == null)   // no more iterators to track
+                itrs = null;
+        }
+
+        /**
+         * Called whenever an interior remove (not at takeIndex) occured.
+         *
+         * Notifies all iterators, and expunges any that are now stale.
+         */
+        void removedAt(int removedIndex) {
+            for (Node o = null, p = head; p != null;) {
+                final Itr it = p.get();
+                final Node next = p.next;
+                if (it == null || it.removedAt(removedIndex)) {
+                    // unlink p
+                    // assert it == null || it.isDetached();
+                    p.clear();
+                    p.next = null;
+                    if (o == null)
+                        head = next;
+                    else
+                        o.next = next;
+                } else {
+                    o = p;
+                }
+                p = next;
+            }
+            if (head == null)   // no more iterators to track
+                itrs = null;
+        }
+
+        /**
+         * Called whenever the queue becomes empty.
+         *
+         * Notifies all active iterators that the queue is empty,
+         * clears all weak refs, and unlinks the itrs datastructure.
+         */
+        void queueIsEmpty() {
+            // assert lock.getHoldCount() == 1;
+            for (Node p = head; p != null; p = p.next) {
+                Itr it = p.get();
+                if (it != null) {
+                    p.clear();
+                    it.shutdown();
+                }
+            }
+            head = null;
+            itrs = null;
+        }
+
+        /**
+         * Called whenever an element has been dequeued (at takeIndex).
+         */
+        void elementDequeued() {
+            // assert lock.getHoldCount() == 1;
+            if (count == 0)
+                queueIsEmpty();
+            else if (takeIndex == 0)
+                takeIndexWrapped();
+        }
+    }
+
+    /**
+     * Iterator for ArrayBlockingQueue.
+     *
+     * To maintain weak consistency with respect to puts and takes, we
+     * read ahead one slot, so as to not report hasNext true but then
+     * not have an element to return.
+     *
+     * We switch into "detached" mode (allowing prompt unlinking from
+     * itrs without help from the GC) when all indices are negative, or
+     * when hasNext returns false for the first time.  This allows the
+     * iterator to track concurrent updates completely accurately,
+     * except for the corner case of the user calling Iterator.remove()
+     * after hasNext() returned false.  Even in this case, we ensure
+     * that we don't remove the wrong element by keeping track of the
+     * expected element to remove, in lastItem.  Yes, we may fail to
+     * remove lastItem from the queue if it moved due to an interleaved
+     * interior remove while in detached mode.
      */
     private class Itr implements Iterator<E> {
-        private int remaining; // Number of elements yet to be returned
-        private int nextIndex; // Index of element to be returned by next
-        private E nextItem;    // Element to be returned by next call to next
-        private E lastItem;    // Element returned by last call to next
-        private int lastRet;   // Index of last element returned, or -1 if none
+        /** Index to look for new nextItem; NONE at end */
+        private int cursor;
+
+        /** Element to be returned by next call to next(); null if none */
+        private E nextItem;
+
+        /** Index of nextItem; NONE if none, REMOVED if removed elsewhere */
+        private int nextIndex;
+
+        /** Last element returned; null if none or not detached. */
+        private E lastItem;
+
+        /** Index of lastItem, NONE if none, REMOVED if removed elsewhere */
+        private int lastRet;
+
+        /** Previous value of takeIndex, or DETACHED when detached */
+        private int prevTakeIndex;
+
+        /** Previous value of iters.cycles */
+        private int prevCycles;
+
+        /** Special index value indicating "not available" or "undefined" */
+        private static final int NONE = -1;
+
+        /**
+         * Special index value indicating "removed elsewhere", that is,
+         * removed by some operation other than a call to this.remove().
+         */
+        private static final int REMOVED = -2;
+
+        /** Special value for prevTakeIndex indicating "detached mode" */
+        private static final int DETACHED = -3;
 
         Itr() {
+            // assert lock.getHoldCount() == 0;
+            lastRet = NONE;
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
             try {
-                lastRet = -1;
-                if ((remaining = count) > 0)
+                if (count == 0) {
+                    // assert itrs == null;
+                    cursor = NONE;
+                    nextIndex = NONE;
+                    prevTakeIndex = DETACHED;
+                } else {
+                    final int takeIndex = ArrayBlockingQueue.this.takeIndex;
+                    prevTakeIndex = takeIndex;
                     nextItem = itemAt(nextIndex = takeIndex);
+                    cursor = incCursor(takeIndex);
+                    if (itrs == null) {
+                        itrs = new Itrs(this);
+                    } else {
+                        itrs.register(this); // in this order
+                        itrs.doSomeSweeping(false);
+                    }
+                    prevCycles = itrs.cycles;
+                    // assert takeIndex >= 0;
+                    // assert prevTakeIndex == takeIndex;
+                    // assert nextIndex >= 0;
+                    // assert nextItem != null;
+                }
             } finally {
                 lock.unlock();
             }
         }
 
-        public boolean hasNext() {
-            return remaining > 0;
+        boolean isDetached() {
+            // assert lock.getHoldCount() == 1;
+            return prevTakeIndex < 0;
+        }
+
+        private int incCursor(int index) {
+            // assert lock.getHoldCount() == 1;
+            if (++index == items.length)
+                index = 0;
+            if (index == putIndex)
+                index = NONE;
+            return index;
+        }
+
+        /**
+         * Returns true if index is invalidated by the given number of
+         * dequeues, starting from prevTakeIndex.
+         */
+        private boolean invalidated(int index, int prevTakeIndex,
+                                    long dequeues, int length) {
+            if (index < 0)
+                return false;
+            int distance = index - prevTakeIndex;
+            if (distance < 0)
+                distance += length;
+            return dequeues > distance;
         }
 
-        public E next() {
+        /**
+         * Adjusts indices to incorporate all dequeues since the last
+         * operation on this iterator.  Call only from iterating thread.
+         */
+        private void incorporateDequeues() {
+            // assert lock.getHoldCount() == 1;
+            // assert itrs != null;
+            // assert !isDetached();
+            // assert count > 0;
+
+            final int cycles = itrs.cycles;
+            final int takeIndex = ArrayBlockingQueue.this.takeIndex;
+            final int prevCycles = this.prevCycles;
+            final int prevTakeIndex = this.prevTakeIndex;
+
+            if (cycles != prevCycles || takeIndex != prevTakeIndex) {
+                final int len = items.length;
+                // how far takeIndex has advanced since the previous
+                // operation of this iterator
+                long dequeues = (cycles - prevCycles) * len
+                    + (takeIndex - prevTakeIndex);
+
+                // Check indices for invalidation
+                if (invalidated(lastRet, prevTakeIndex, dequeues, len))
+                    lastRet = REMOVED;
+                if (invalidated(nextIndex, prevTakeIndex, dequeues, len))
+                    nextIndex = REMOVED;
+                if (invalidated(cursor, prevTakeIndex, dequeues, len))
+                    cursor = takeIndex;
+
+                if (cursor < 0 && nextIndex < 0 && lastRet < 0)
+                    detach();
+                else {
+                    this.prevCycles = cycles;
+                    this.prevTakeIndex = takeIndex;
+                }
+            }
+        }
+
+        /**
+         * Called when itrs should stop tracking this iterator, either
+         * because there are no more indices to update (cursor < 0 &&
+         * nextIndex < 0 && lastRet < 0) or as a special exception, when
+         * lastRet >= 0, because hasNext() is about to return false for the
+         * first time.  Call only from iterating thread.
+         */
+        private void detach() {
+            // Switch to detached mode
+            // assert lock.getHoldCount() == 1;
+            // assert cursor == NONE;
+            // assert nextIndex < 0;
+            // assert lastRet < 0 || nextItem == null;
+            // assert lastRet < 0 ^ lastItem != null;
+            if (prevTakeIndex >= 0) {
+                // assert itrs != null;
+                prevTakeIndex = DETACHED;
+                // try to unlink from itrs (but not too hard)
+                itrs.doSomeSweeping(true);
+            }
+        }
+
+        /**
+         * For performance reasons, we would like not to acquire a lock in
+         * hasNext in the common case.  To allow for this, we only access
+         * fields (i.e. nextItem) that are not modified by update operations
+         * triggered by queue modifications.
+         */
+        public boolean hasNext() {
+            // assert lock.getHoldCount() == 0;
+            if (nextItem != null)
+                return true;
+            noNext();
+            return false;
+        }
+
+        private void noNext() {
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
             try {
-                if (remaining <= 0)
-                    throw new NoSuchElementException();
-                lastRet = nextIndex;
-                E x = itemAt(nextIndex);  // check for fresher value
-                if (x == null) {
-                    x = nextItem;         // we are forced to report old value
-                    lastItem = null;      // but ensure remove fails
+                // assert cursor == NONE;
+                // assert nextIndex == NONE;
+                if (!isDetached()) {
+                    // assert lastRet >= 0;
+                    incorporateDequeues(); // might update lastRet
+                    if (lastRet >= 0) {
+                        lastItem = itemAt(lastRet);
+                        // assert lastItem != null;
+                        detach();
+                    }
                 }
-                else
-                    lastItem = x;
-                while (--remaining > 0 && // skip over nulls
-                       (nextItem = itemAt(nextIndex = inc(nextIndex))) == null)
-                    ;
-                return x;
+                // assert isDetached();
+                // assert lastRet < 0 ^ lastItem != null;
             } finally {
                 lock.unlock();
             }
         }
 
-        public void remove() {
+        public E next() {
+            // assert lock.getHoldCount() == 0;
+            final E x = nextItem;
+            if (x == null)
+                throw new NoSuchElementException();
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
             try {
-                int i = lastRet;
-                if (i == -1)
-                    throw new IllegalStateException();
-                lastRet = -1;
-                E x = lastItem;
-                lastItem = null;
-                // only remove if item still at index
-                if (x != null && x == items[i]) {
-                    boolean removingHead = (i == takeIndex);
-                    removeAt(i);
-                    if (!removingHead)
-                        nextIndex = dec(nextIndex);
+                if (!isDetached())
+                    incorporateDequeues();
+                // assert nextIndex != NONE;
+                // assert lastItem == null;
+                lastRet = nextIndex;
+                final int cursor = this.cursor;
+                if (cursor >= 0) {
+                    nextItem = itemAt(nextIndex = cursor);
+                    // assert nextItem != null;
+                    this.cursor = incCursor(cursor);
+                } else {
+                    nextIndex = NONE;
+                    nextItem = null;
                 }
             } finally {
                 lock.unlock();
             }
+            return x;
         }
+
+        public void remove() {
+            // assert lock.getHoldCount() == 0;
+            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+            lock.lock();
+            try {
+                if (!isDetached())
+                    incorporateDequeues(); // might update lastRet or detach
+                final int lastRet = this.lastRet;
+                this.lastRet = NONE;
+                if (lastRet >= 0) {
+                    if (!isDetached())
+                        removeAt(lastRet);
+                    else {
+                        final E lastItem = this.lastItem;
+                        // assert lastItem != null;
+                        this.lastItem = null;
+                        if (itemAt(lastRet) == lastItem)
+                            removeAt(lastRet);
+                    }
+                } else if (lastRet == NONE)
+                    throw new IllegalStateException();
+                // else lastRet == REMOVED and the last returned element was
+                // previously asynchronously removed via an operation other
+                // than this.remove(), so nothing to do.
+
+                if (cursor < 0 && nextIndex < 0)
+                    detach();
+            } finally {
+                lock.unlock();
+                // assert lastRet == NONE;
+                // assert lastItem == null;
+            }
+        }
+
+        /**
+         * Called to notify the iterator that the queue is empty, or that it
+         * has fallen hopelessly behind, so that it should abandon any
+         * further iteration, except possibly to return one more element
+         * from next(), as promised by returning true from hasNext().
+         */
+        void shutdown() {
+            // assert lock.getHoldCount() == 1;
+            cursor = NONE;
+            if (nextIndex >= 0)
+                nextIndex = REMOVED;
+            if (lastRet >= 0) {
+                lastRet = REMOVED;
+                lastItem = null;
+            }
+            prevTakeIndex = DETACHED;
+            // Don't set nextItem to null because we must continue to be
+            // able to return it on next().
+            //
+            // Caller will unlink from itrs when convenient.
+        }
+
+        private int distance(int index, int prevTakeIndex, int length) {
+            int distance = index - prevTakeIndex;
+            if (distance < 0)
+                distance += length;
+            return distance;
+        }
+
+        /**
+         * Called whenever an interior remove (not at takeIndex) occured.
+         *
+         * @return true if this iterator should be unlinked from itrs
+         */
+        boolean removedAt(int removedIndex) {
+            // assert lock.getHoldCount() == 1;
+            if (isDetached())
+                return true;
+
+            final int cycles = itrs.cycles;
+            final int takeIndex = ArrayBlockingQueue.this.takeIndex;
+            final int prevCycles = this.prevCycles;
+            final int prevTakeIndex = this.prevTakeIndex;
+            final int len = items.length;
+            int cycleDiff = cycles - prevCycles;
+            if (removedIndex < takeIndex)
+                cycleDiff++;
+            final int removedDistance =
+                (cycleDiff * len) + (removedIndex - prevTakeIndex);
+            // assert removedDistance >= 0;
+            int cursor = this.cursor;
+            if (cursor >= 0) {
+                int x = distance(cursor, prevTakeIndex, len);
+                if (x == removedDistance) {
+                    if (cursor == putIndex)
+                        this.cursor = cursor = NONE;
+                }
+                else if (x > removedDistance) {
+                    // assert cursor != prevTakeIndex;
+                    this.cursor = cursor = dec(cursor);
+                }
+            }
+            int lastRet = this.lastRet;
+            if (lastRet >= 0) {
+                int x = distance(lastRet, prevTakeIndex, len);
+                if (x == removedDistance)
+                    this.lastRet = lastRet = REMOVED;
+                else if (x > removedDistance)
+                    this.lastRet = lastRet = dec(lastRet);
+            }
+            int nextIndex = this.nextIndex;
+            if (nextIndex >= 0) {
+                int x = distance(nextIndex, prevTakeIndex, len);
+                if (x == removedDistance)
+                    this.nextIndex = nextIndex = REMOVED;
+                else if (x > removedDistance)
+                    this.nextIndex = nextIndex = dec(nextIndex);
+            }
+            else if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
+                this.prevTakeIndex = DETACHED;
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Called whenever takeIndex wraps around to zero.
+         *
+         * @return true if this iterator should be unlinked from itrs
+         */
+        boolean takeIndexWrapped() {
+            // assert lock.getHoldCount() == 1;
+            if (isDetached())
+                return true;
+            if (itrs.cycles - prevCycles > 1) {
+                // All the elements that existed at the time of the last
+                // operation are gone, so abandon further iteration.
+                shutdown();
+                return true;
+            }
+            return false;
+        }
+
+//         /** Uncomment for debugging. */
+//         public String toString() {
+//             return ("cursor=" + cursor + " " +
+//                     "nextIndex=" + nextIndex + " " +
+//                     "lastRet=" + lastRet + " " +
+//                     "nextItem=" + nextItem + " " +
+//                     "lastItem=" + lastItem + " " +
+//                     "prevCycles=" + prevCycles + " " +
+//                     "prevTakeIndex=" + prevTakeIndex + " " +
+//                     "size()=" + size() + " " +
+//                     "remainingCapacity()=" + remainingCapacity());
+//         }
     }
 
+    public Spliterator<E> spliterator() {
+        return Spliterators.spliterator
+            (this, Spliterator.ORDERED | Spliterator.NONNULL |
+             Spliterator.CONCURRENT);
+    }
 }
--- a/jdk/src/share/classes/java/util/concurrent/BlockingDeque.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/BlockingDeque.java	Wed Jul 03 11:58:09 2013 +0200
@@ -41,17 +41,18 @@
  * for the deque to become non-empty when retrieving an element, and wait for
  * space to become available in the deque when storing an element.
  *
- * <p><tt>BlockingDeque</tt> methods come in four forms, with different ways
+ * <p>{@code BlockingDeque} methods come in four forms, with different ways
  * of handling operations that cannot be satisfied immediately, but may be
  * satisfied at some point in the future:
  * one throws an exception, the second returns a special value (either
- * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * {@code null} or {@code false}, depending on the operation), the third
  * blocks the current thread indefinitely until the operation can succeed,
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
  *
  * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <caption>Summary of BlockingDeque methods</caption>
  *  <tr>
  *    <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
  *  </tr>
@@ -116,20 +117,21 @@
  *  </tr>
  * </table>
  *
- * <p>Like any {@link BlockingQueue}, a <tt>BlockingDeque</tt> is thread safe,
+ * <p>Like any {@link BlockingQueue}, a {@code BlockingDeque} is thread safe,
  * does not permit null elements, and may (or may not) be
  * capacity-constrained.
  *
- * <p>A <tt>BlockingDeque</tt> implementation may be used directly as a FIFO
- * <tt>BlockingQueue</tt>. The methods inherited from the
- * <tt>BlockingQueue</tt> interface are precisely equivalent to
- * <tt>BlockingDeque</tt> methods as indicated in the following table:
+ * <p>A {@code BlockingDeque} implementation may be used directly as a FIFO
+ * {@code BlockingQueue}. The methods inherited from the
+ * {@code BlockingQueue} interface are precisely equivalent to
+ * {@code BlockingDeque} methods as indicated in the following table:
  *
  * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <caption>Comparison of BlockingQueue and BlockingDeque methods</caption>
  *  <tr>
- *    <td ALIGN=CENTER> <b><tt>BlockingQueue</tt> Method</b></td>
- *    <td ALIGN=CENTER> <b>Equivalent <tt>BlockingDeque</tt> Method</b></td>
+ *    <td ALIGN=CENTER> <b>{@code BlockingQueue} Method</b></td>
+ *    <td ALIGN=CENTER> <b>Equivalent {@code BlockingDeque} Method</b></td>
  *  </tr>
  *  <tr>
  *    <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
@@ -208,7 +210,7 @@
     /**
      * Inserts the specified element at the front of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * throwing an <tt>IllegalStateException</tt> if no space is currently
+     * throwing an {@code IllegalStateException} if no space is currently
      * available.  When using a capacity-restricted deque, it is generally
      * preferable to use {@link #offerFirst(Object) offerFirst}.
      *
@@ -223,7 +225,7 @@
     /**
      * Inserts the specified element at the end of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * throwing an <tt>IllegalStateException</tt> if no space is currently
+     * throwing an {@code IllegalStateException} if no space is currently
      * available.  When using a capacity-restricted deque, it is generally
      * preferable to use {@link #offerLast(Object) offerLast}.
      *
@@ -238,7 +240,7 @@
     /**
      * Inserts the specified element at the front of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+     * returning {@code true} upon success and {@code false} if no space is
      * currently available.
      * When using a capacity-restricted deque, this method is generally
      * preferable to the {@link #addFirst(Object) addFirst} method, which can
@@ -254,7 +256,7 @@
     /**
      * Inserts the specified element at the end of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+     * returning {@code true} upon success and {@code false} if no space is
      * currently available.
      * When using a capacity-restricted deque, this method is generally
      * preferable to the {@link #addLast(Object) addLast} method, which can
@@ -302,10 +304,10 @@
      *
      * @param e the element to add
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available
      * @throws InterruptedException if interrupted while waiting
      * @throws ClassCastException if the class of the specified element
@@ -324,10 +326,10 @@
      *
      * @param e the element to add
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available
      * @throws InterruptedException if interrupted while waiting
      * @throws ClassCastException if the class of the specified element
@@ -363,10 +365,10 @@
      * become available.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return the head of this deque, or <tt>null</tt> if the specified
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the head of this deque, or {@code null} if the specified
      *         waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -379,10 +381,10 @@
      * become available.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return the tail of this deque, or <tt>null</tt> if the specified
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the tail of this deque, or {@code null} if the specified
      *         waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -392,13 +394,13 @@
     /**
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the first element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if an element was removed as a result of this call
+     * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -410,13 +412,13 @@
     /**
      * Removes the last occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the last element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the last element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if an element was removed as a result of this call
+     * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -431,8 +433,8 @@
      * Inserts the specified element into the queue represented by this deque
      * (in other words, at the tail of this deque) if it is possible to do so
      * immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and throwing an
-     * <tt>IllegalStateException</tt> if no space is currently available.
+     * {@code true} upon success and throwing an
+     * {@code IllegalStateException} if no space is currently available.
      * When using a capacity-restricted deque, it is generally preferable to
      * use {@link #offer(Object) offer}.
      *
@@ -452,7 +454,7 @@
      * Inserts the specified element into the queue represented by this deque
      * (in other words, at the tail of this deque) if it is possible to do so
      * immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+     * {@code true} upon success and {@code false} if no space is currently
      * available.  When using a capacity-restricted deque, this method is
      * generally preferable to the {@link #add} method, which can fail to
      * insert an element only by throwing an exception.
@@ -494,8 +496,8 @@
      * {@link #offerLast(Object,long,TimeUnit) offerLast}.
      *
      * @param e the element to add
-     * @return <tt>true</tt> if the element was added to this deque, else
-     *         <tt>false</tt>
+     * @return {@code true} if the element was added to this deque, else
+     *         {@code false}
      * @throws InterruptedException {@inheritDoc}
      * @throws ClassCastException if the class of the specified element
      *         prevents it from being added to this deque
@@ -522,11 +524,11 @@
     /**
      * Retrieves and removes the head of the queue represented by this deque
      * (in other words, the first element of this deque), or returns
-     * <tt>null</tt> if this deque is empty.
+     * {@code null} if this deque is empty.
      *
      * <p>This method is equivalent to {@link #pollFirst()}.
      *
-     * @return the head of this deque, or <tt>null</tt> if this deque is empty
+     * @return the head of this deque, or {@code null} if this deque is empty
      */
     E poll();
 
@@ -550,7 +552,7 @@
      * <p>This method is equivalent to
      * {@link #pollFirst(long,TimeUnit) pollFirst}.
      *
-     * @return the head of this deque, or <tt>null</tt> if the
+     * @return the head of this deque, or {@code null} if the
      *         specified waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -573,27 +575,27 @@
     /**
      * Retrieves, but does not remove, the head of the queue represented by
      * this deque (in other words, the first element of this deque), or
-     * returns <tt>null</tt> if this deque is empty.
+     * returns {@code null} if this deque is empty.
      *
      * <p>This method is equivalent to {@link #peekFirst() peekFirst}.
      *
-     * @return the head of this deque, or <tt>null</tt> if this deque is empty
+     * @return the head of this deque, or {@code null} if this deque is empty
      */
     E peek();
 
     /**
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the first element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * <p>This method is equivalent to
      * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if this deque changed as a result of the call
+     * @return {@code true} if this deque changed as a result of the call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -603,12 +605,12 @@
     boolean remove(Object o);
 
     /**
-     * Returns <tt>true</tt> if this deque contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this deque contains
-     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this deque contains the specified element.
+     * More formally, returns {@code true} if and only if this deque contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this deque
-     * @return <tt>true</tt> if this deque contains the specified element
+     * @return {@code true} if this deque contains the specified element
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -635,9 +637,10 @@
     // *** Stack methods ***
 
     /**
-     * Pushes an element onto the stack represented by this deque.  In other
-     * words, inserts the element at the front of this deque unless it would
-     * violate capacity restrictions.
+     * Pushes an element onto the stack represented by this deque (in other
+     * words, at the head of this deque) if it is possible to do so
+     * immediately without violating capacity restrictions, throwing an
+     * {@code IllegalStateException} if no space is currently available.
      *
      * <p>This method is equivalent to {@link #addFirst(Object) addFirst}.
      *
--- a/jdk/src/share/classes/java/util/concurrent/BlockingQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/BlockingQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -44,17 +44,18 @@
  * element, and wait for space to become available in the queue when
  * storing an element.
  *
- * <p><tt>BlockingQueue</tt> methods come in four forms, with different ways
+ * <p>{@code BlockingQueue} methods come in four forms, with different ways
  * of handling operations that cannot be satisfied immediately, but may be
  * satisfied at some point in the future:
  * one throws an exception, the second returns a special value (either
- * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * {@code null} or {@code false}, depending on the operation), the third
  * blocks the current thread indefinitely until the operation can succeed,
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
  *
  * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <caption>Summary of BlockingQueue methods</caption>
  *  <tr>
  *    <td></td>
  *    <td ALIGN=CENTER><em>Throws exception</em></td>
@@ -85,37 +86,37 @@
  *  </tr>
  * </table>
  *
- * <p>A <tt>BlockingQueue</tt> does not accept <tt>null</tt> elements.
- * Implementations throw <tt>NullPointerException</tt> on attempts
- * to <tt>add</tt>, <tt>put</tt> or <tt>offer</tt> a <tt>null</tt>.  A
- * <tt>null</tt> is used as a sentinel value to indicate failure of
- * <tt>poll</tt> operations.
+ * <p>A {@code BlockingQueue} does not accept {@code null} elements.
+ * Implementations throw {@code NullPointerException} on attempts
+ * to {@code add}, {@code put} or {@code offer} a {@code null}.  A
+ * {@code null} is used as a sentinel value to indicate failure of
+ * {@code poll} operations.
  *
- * <p>A <tt>BlockingQueue</tt> may be capacity bounded. At any given
- * time it may have a <tt>remainingCapacity</tt> beyond which no
- * additional elements can be <tt>put</tt> without blocking.
- * A <tt>BlockingQueue</tt> without any intrinsic capacity constraints always
- * reports a remaining capacity of <tt>Integer.MAX_VALUE</tt>.
+ * <p>A {@code BlockingQueue} may be capacity bounded. At any given
+ * time it may have a {@code remainingCapacity} beyond which no
+ * additional elements can be {@code put} without blocking.
+ * A {@code BlockingQueue} without any intrinsic capacity constraints always
+ * reports a remaining capacity of {@code Integer.MAX_VALUE}.
  *
- * <p> <tt>BlockingQueue</tt> implementations are designed to be used
+ * <p>{@code BlockingQueue} implementations are designed to be used
  * primarily for producer-consumer queues, but additionally support
  * the {@link java.util.Collection} interface.  So, for example, it is
  * possible to remove an arbitrary element from a queue using
- * <tt>remove(x)</tt>. However, such operations are in general
+ * {@code remove(x)}. However, such operations are in general
  * <em>not</em> performed very efficiently, and are intended for only
  * occasional use, such as when a queued message is cancelled.
  *
- * <p> <tt>BlockingQueue</tt> implementations are thread-safe.  All
+ * <p>{@code BlockingQueue} implementations are thread-safe.  All
  * queuing methods achieve their effects atomically using internal
  * locks or other forms of concurrency control. However, the
- * <em>bulk</em> Collection operations <tt>addAll</tt>,
- * <tt>containsAll</tt>, <tt>retainAll</tt> and <tt>removeAll</tt> are
+ * <em>bulk</em> Collection operations {@code addAll},
+ * {@code containsAll}, {@code retainAll} and {@code removeAll} are
  * <em>not</em> necessarily performed atomically unless specified
  * otherwise in an implementation. So it is possible, for example, for
- * <tt>addAll(c)</tt> to fail (throwing an exception) after adding
- * only some of the elements in <tt>c</tt>.
+ * {@code addAll(c)} to fail (throwing an exception) after adding
+ * only some of the elements in {@code c}.
  *
- * <p>A <tt>BlockingQueue</tt> does <em>not</em> intrinsically support
+ * <p>A {@code BlockingQueue} does <em>not</em> intrinsically support
  * any kind of &quot;close&quot; or &quot;shutdown&quot; operation to
  * indicate that no more items will be added.  The needs and usage of
  * such features tend to be implementation-dependent. For example, a
@@ -125,7 +126,7 @@
  *
  * <p>
  * Usage example, based on a typical producer-consumer scenario.
- * Note that a <tt>BlockingQueue</tt> can safely be used with multiple
+ * Note that a {@code BlockingQueue} can safely be used with multiple
  * producers and multiple consumers.
  *  <pre> {@code
  * class Producer implements Runnable {
@@ -181,13 +182,13 @@
     /**
      * Inserts the specified element into this queue if it is possible to do
      * so immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and throwing an
-     * <tt>IllegalStateException</tt> if no space is currently available.
+     * {@code true} upon success and throwing an
+     * {@code IllegalStateException} if no space is currently available.
      * When using a capacity-restricted queue, it is generally preferable to
      * use {@link #offer(Object) offer}.
      *
      * @param e the element to add
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      * @throws IllegalStateException if the element cannot be added at this
      *         time due to capacity restrictions
      * @throws ClassCastException if the class of the specified element
@@ -201,14 +202,14 @@
     /**
      * Inserts the specified element into this queue if it is possible to do
      * so immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+     * {@code true} upon success and {@code false} if no space is currently
      * available.  When using a capacity-restricted queue, this method is
      * generally preferable to {@link #add}, which can fail to insert an
      * element only by throwing an exception.
      *
      * @param e the element to add
-     * @return <tt>true</tt> if the element was added to this queue, else
-     *         <tt>false</tt>
+     * @return {@code true} if the element was added to this queue, else
+     *         {@code false}
      * @throws ClassCastException if the class of the specified element
      *         prevents it from being added to this queue
      * @throws NullPointerException if the specified element is null
@@ -237,10 +238,10 @@
      *
      * @param e the element to add
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available
      * @throws InterruptedException if interrupted while waiting
      * @throws ClassCastException if the class of the specified element
@@ -266,10 +267,10 @@
      * specified wait time if necessary for an element to become available.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return the head of this queue, or <tt>null</tt> if the
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the head of this queue, or {@code null} if the
      *         specified waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -279,11 +280,11 @@
     /**
      * Returns the number of additional elements that this queue can ideally
      * (in the absence of memory or resource constraints) accept without
-     * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+     * blocking, or {@code Integer.MAX_VALUE} if there is no intrinsic
      * limit.
      *
      * <p>Note that you <em>cannot</em> always tell if an attempt to insert
-     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * an element will succeed by inspecting {@code remainingCapacity}
      * because it may be the case that another thread is about to
      * insert or remove an element.
      *
@@ -293,14 +294,14 @@
 
     /**
      * Removes a single instance of the specified element from this queue,
-     * if it is present.  More formally, removes an element <tt>e</tt> such
-     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
      * elements.
-     * Returns <tt>true</tt> if this queue contained the specified element
+     * Returns {@code true} if this queue contained the specified element
      * (or equivalently, if this queue changed as a result of the call).
      *
      * @param o element to be removed from this queue, if present
-     * @return <tt>true</tt> if this queue changed as a result of the call
+     * @return {@code true} if this queue changed as a result of the call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this queue
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -310,12 +311,12 @@
     boolean remove(Object o);
 
     /**
-     * Returns <tt>true</tt> if this queue contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this queue contains
-     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this queue contains the specified element.
+     * More formally, returns {@code true} if and only if this queue contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this queue
-     * @return <tt>true</tt> if this queue contains the specified element
+     * @return {@code true} if this queue contains the specified element
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this queue
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -329,10 +330,10 @@
      * to the given collection.  This operation may be more
      * efficient than repeatedly polling this queue.  A failure
      * encountered while attempting to add elements to
-     * collection <tt>c</tt> may result in elements being in neither,
+     * collection {@code c} may result in elements being in neither,
      * either or both collections when the associated exception is
      * thrown.  Attempts to drain a queue to itself result in
-     * <tt>IllegalArgumentException</tt>. Further, the behavior of
+     * {@code IllegalArgumentException}. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
@@ -353,10 +354,10 @@
      * Removes at most the given number of available elements from
      * this queue and adds them to the given collection.  A failure
      * encountered while attempting to add elements to
-     * collection <tt>c</tt> may result in elements being in neither,
+     * collection {@code c} may result in elements being in neither,
      * either or both collections when the associated exception is
      * thrown.  Attempts to drain a queue to itself result in
-     * <tt>IllegalArgumentException</tt>. Further, the behavior of
+     * {@code IllegalArgumentException}. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Wed Jul 03 11:58:09 2013 +0200
@@ -42,6 +42,9 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
 
 /**
  * An unbounded concurrent {@linkplain Deque deque} based on linked nodes.
@@ -816,7 +819,7 @@
      * Creates an array list and fills it with elements of this list.
      * Used by toArray.
      *
-     * @return the arrayList
+     * @return the array list
      */
     private ArrayList<E> toArrayList() {
         ArrayList<E> list = new ArrayList<E>();
@@ -1024,11 +1027,27 @@
     }
 
     public E poll()           { return pollFirst(); }
+    public E peek()           { return peekFirst(); }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
     public E remove()         { return removeFirst(); }
-    public E peek()           { return peekFirst(); }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
+    public E pop()            { return removeFirst(); }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
     public E element()        { return getFirst(); }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
     public void push(E e)     { addFirst(e); }
-    public E pop()            { return removeFirst(); }
 
     /**
      * Removes the first element {@code e} such that
@@ -1385,6 +1404,99 @@
         Node<E> nextNode(Node<E> p) { return pred(p); }
     }
 
+    /** A customized variant of Spliterators.IteratorSpliterator */
+    static final class CLDSpliterator<E> implements Spliterator<E> {
+        static final int MAX_BATCH = 1 << 25;  // max batch array size;
+        final ConcurrentLinkedDeque<E> queue;
+        Node<E> current;    // current node; null until initialized
+        int batch;          // batch size for splits
+        boolean exhausted;  // true when no more nodes
+        CLDSpliterator(ConcurrentLinkedDeque<E> queue) {
+            this.queue = queue;
+        }
+
+        public Spliterator<E> trySplit() {
+            Node<E> p;
+            final ConcurrentLinkedDeque<E> q = this.queue;
+            int b = batch;
+            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.first()) != null)) {
+                if (p.item == null && p == (p = p.next))
+                    current = p = q.first();
+                if (p != null && p.next != null) {
+                    Object[] a = new Object[n];
+                    int i = 0;
+                    do {
+                        if ((a[i] = p.item) != null)
+                            ++i;
+                        if (p == (p = p.next))
+                            p = q.first();
+                    } while (p != null && i < n);
+                    if ((current = p) == null)
+                        exhausted = true;
+                    if (i > 0) {
+                        batch = i;
+                        return Spliterators.spliterator
+                            (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                             Spliterator.CONCURRENT);
+                    }
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            Node<E> p;
+            if (action == null) throw new NullPointerException();
+            final ConcurrentLinkedDeque<E> q = this.queue;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.first()) != null)) {
+                exhausted = true;
+                do {
+                    E e = p.item;
+                    if (p == (p = p.next))
+                        p = q.first();
+                    if (e != null)
+                        action.accept(e);
+                } while (p != null);
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            Node<E> p;
+            if (action == null) throw new NullPointerException();
+            final ConcurrentLinkedDeque<E> q = this.queue;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.first()) != null)) {
+                E e;
+                do {
+                    e = p.item;
+                    if (p == (p = p.next))
+                        p = q.first();
+                } while (e == null && p != null);
+                if ((current = p) == null)
+                    exhausted = true;
+                if (e != null) {
+                    action.accept(e);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public long estimateSize() { return Long.MAX_VALUE; }
+
+        public int characteristics() {
+            return Spliterator.ORDERED | Spliterator.NONNULL |
+                Spliterator.CONCURRENT;
+        }
+    }
+
+    public Spliterator<E> spliterator() {
+        return new CLDSpliterator<E>(this);
+    }
+
     /**
      * Saves this deque to a stream (that is, serializes it).
      *
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -41,6 +41,9 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
 
 /**
  * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
@@ -56,7 +59,7 @@
  * Like most other concurrent collection implementations, this class
  * does not permit the use of {@code null} elements.
  *
- * <p>This implementation employs an efficient &quot;wait-free&quot;
+ * <p>This implementation employs an efficient <em>non-blocking</em>
  * algorithm based on one described in <a
  * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
  * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
@@ -295,7 +298,7 @@
     }
 
     /**
-     * Try to CAS head to p. If successful, repoint old head to itself
+     * Tries to CAS head to p. If successful, repoint old head to itself
      * as sentinel for succ(), below.
      */
     final void updateHead(Node<E> h, Node<E> p) {
@@ -792,6 +795,96 @@
         tail = t;
     }
 
+    /** A customized variant of Spliterators.IteratorSpliterator */
+    static final class CLQSpliterator<E> implements Spliterator<E> {
+        static final int MAX_BATCH = 1 << 25;  // max batch array size;
+        final ConcurrentLinkedQueue<E> queue;
+        Node<E> current;    // current node; null until initialized
+        int batch;          // batch size for splits
+        boolean exhausted;  // true when no more nodes
+        CLQSpliterator(ConcurrentLinkedQueue<E> queue) {
+            this.queue = queue;
+        }
+
+        public Spliterator<E> trySplit() {
+            Node<E> p;
+            final ConcurrentLinkedQueue<E> q = this.queue;
+            int b = batch;
+            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.first()) != null) &&
+                p.next != null) {
+                Object[] a = new Object[n];
+                int i = 0;
+                do {
+                    if ((a[i] = p.item) != null)
+                        ++i;
+                    if (p == (p = p.next))
+                        p = q.first();
+                } while (p != null && i < n);
+                if ((current = p) == null)
+                    exhausted = true;
+                if (i > 0) {
+                    batch = i;
+                    return Spliterators.spliterator
+                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                         Spliterator.CONCURRENT);
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            Node<E> p;
+            if (action == null) throw new NullPointerException();
+            final ConcurrentLinkedQueue<E> q = this.queue;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.first()) != null)) {
+                exhausted = true;
+                do {
+                    E e = p.item;
+                    if (p == (p = p.next))
+                        p = q.first();
+                    if (e != null)
+                        action.accept(e);
+                } while (p != null);
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            Node<E> p;
+            if (action == null) throw new NullPointerException();
+            final ConcurrentLinkedQueue<E> q = this.queue;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.first()) != null)) {
+                E e;
+                do {
+                    e = p.item;
+                    if (p == (p = p.next))
+                        p = q.first();
+                } while (e == null && p != null);
+                if ((current = p) == null)
+                    exhausted = true;
+                if (e != null) {
+                    action.accept(e);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public long estimateSize() { return Long.MAX_VALUE; }
+
+        public int characteristics() {
+            return Spliterator.ORDERED | Spliterator.NONNULL |
+                Spliterator.CONCURRENT;
+        }
+    }
+
+    public Spliterator<E> spliterator() {
+        return new CLQSpliterator<E>(this);
+    }
+
     /**
      * Throws NullPointerException if argument is null.
      *
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Wed Jul 03 11:58:09 2013 +0200
@@ -34,7 +34,25 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.Spliterator;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
 
 /**
  * A scalable concurrent {@link ConcurrentNavigableMap} implementation.
@@ -45,38 +63,38 @@
  * <p>This class implements a concurrent variant of <a
  * href="http://en.wikipedia.org/wiki/Skip_list" target="_top">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,
+ * {@code containsKey}, {@code get}, {@code put} and
+ * {@code remove} 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.
+ * java.util.ConcurrentModificationException 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
+ * <p>All {@code Map.Entry} 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>
+ * produced. They do <em>not</em> support the {@code Entry.setValue}
  * 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.)
+ * associated map using {@code put}, {@code putIfAbsent}, or
+ * {@code replace}, depending on exactly which effect you need.)
  *
- * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * <p>Beware that, unlike in most collections, the {@code size}
  * 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, and so may report
  * inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations <tt>putAll</tt>, <tt>equals</tt>,
- * <tt>toArray</tt>, <tt>containsValue</tt>, and <tt>clear</tt> are
+ * Additionally, the bulk operations {@code putAll}, {@code equals},
+ * {@code toArray}, {@code containsValue}, and {@code clear} are
  * <em>not</em> guaranteed to be performed atomically. For example, an
- * iterator operating concurrently with a <tt>putAll</tt> operation
+ * iterator operating concurrently with a {@code putAll} 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
- * <em>not</em> permit the use of <tt>null</tt> keys or values because some
+ * <em>not</em> permit the use of {@code null} keys or values because some
  * null return values cannot be reliably distinguished from the absence of
  * elements.
  *
@@ -89,7 +107,6 @@
  * @param <V> the type of mapped values
  * @since 1.6
  */
-@SuppressWarnings("unchecked")
 public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
     implements ConcurrentNavigableMap<K,V>,
                Cloneable,
@@ -257,7 +274,7 @@
      *
      * 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
+     * hardwired parameters k=1, p=0.5 (see method doPut) 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
@@ -295,6 +312,20 @@
      * there is a fair amount of near-duplication of code to handle
      * variants.
      *
+     * To produce random values without interference across threads,
+     * we use within-JDK thread local random support (via the
+     * "secondary seed", to avoid interference with user-level
+     * ThreadLocalRandom.)
+     *
+     * A previous version of this class wrapped non-comparable keys
+     * with their comparators to emulate Comparables when using
+     * comparators vs Comparables.  However, JVMs now appear to better
+     * handle infusing comparator-vs-comparable choice into search
+     * loops. Static method cpr(comparator, x, y) is used for all
+     * comparisons, which works well as long as the comparator
+     * argument is set up outside of loops (thus sometimes passed as
+     * an argument to internal methods) to avoid field re-reads.
+     *
      * 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
@@ -323,12 +354,6 @@
     private static final long serialVersionUID = -8627078645895051609L;
 
     /**
-     * Generates the initial random seed for the cheaper per-instance
-     * random number generators used in randomLevel.
-     */
-    private static final Random seedGenerator = new Random();
-
-    /**
      * Special value used to identify base-level header
      */
     private static final Object BASE_HEADER = new Object();
@@ -339,17 +364,12 @@
     private transient volatile HeadIndex<K,V> head;
 
     /**
-     * The comparator used to maintain order in this map, or null
-     * if using natural ordering.
+     * The comparator used to maintain order in this map, or null if
+     * using natural ordering.  (Non-private to simplify access in
+     * nested classes.)
      * @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;
+    final Comparator<? super K> comparator;
 
     /** Lazily initialized key set */
     private transient KeySet<K> keySet;
@@ -365,12 +385,11 @@
      * clear, readObject. and ConcurrentSkipListSet.clone.
      * (Note that comparator must be separately initialized.)
      */
-    final void initialize() {
+    private void initialize() {
         keySet = null;
         entrySet = null;
         values = null;
         descendingMap = null;
-        randomSeed = seedGenerator.nextInt() | 0x0100; // ensure nonzero
         head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
                                   null, null, 1);
     }
@@ -438,7 +457,7 @@
          * 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() {
@@ -477,7 +496,7 @@
              */
             if (f == next && this == b.next) {
                 if (f == null || f.value != f) // not already marked
-                    appendMarker(f);
+                    casNext(f, new Node<K,V>(f));
                 else
                     b.casNext(this, f.next);
             }
@@ -487,13 +506,14 @@
          * Returns 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.
+         * is deleted, else null
          */
         V getValidValue() {
             Object v = value;
             if (v == this || v == BASE_HEADER)
                 return null;
-            return (V)v;
+            @SuppressWarnings("unchecked") V vv = (V)v;
+            return vv;
         }
 
         /**
@@ -502,10 +522,11 @@
          * @return new entry or null
          */
         AbstractMap.SimpleImmutableEntry<K,V> createSnapshot() {
-            V v = getValidValue();
-            if (v == null)
+            Object v = value;
+            if (v == null || v == this || v == BASE_HEADER)
                 return null;
-            return new AbstractMap.SimpleImmutableEntry<K,V>(key, v);
+            @SuppressWarnings("unchecked") V vv = (V)v;
+            return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
         }
 
         // UNSAFE mechanics
@@ -588,7 +609,7 @@
          * @return true if successful
          */
         final boolean unlink(Index<K,V> succ) {
-            return !indexesDeletedNode() && casRight(succ, succ.right);
+            return node.value != null && casRight(succ, succ.right);
         }
 
         // Unsafe mechanics
@@ -622,80 +643,12 @@
     /* ---------------- Comparison utilities -------------- */
 
     /**
-     * Represents a key with a comparator as a Comparable.
-     *
-     * Because most sorted collections seem to use natural ordering 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 Comparable, which may cause ClassCastException,
-     * which is propagated back to caller.
+     * Compares using comparator or natural ordering if null.
+     * Called only by methods that have performed required type checks.
      */
-    private Comparable<? super K> comparable(Object key)
-            throws ClassCastException {
-        if (key == null)
-            throw new NullPointerException();
-        if (comparator != null)
-            return new ComparableUsingComparator<K>((K)key, comparator);
-        else
-            return (Comparable<? super K>)key;
-    }
-
-    /**
-     * Compares 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<? super K>)k1).compareTo(k2);
-    }
-
-    /**
-     * Returns true if given key greater than or equal to least and
-     * strictly less than fence, bypassing either test if least or
-     * fence are 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));
-    }
-
-    /**
-     * Returns 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));
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    static final int cpr(Comparator c, Object x, Object y) {
+        return (c != null) ? c.compare(x, y) : ((Comparable)x).compareTo(y);
     }
 
     /* ---------------- Traversal -------------- */
@@ -708,13 +661,11 @@
      * @param key the key
      * @return a predecessor of key
      */
-    private Node<K,V> findPredecessor(Comparable<? super K> key) {
+    private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) {
         if (key == null)
             throw new NullPointerException(); // don't postpone errors
         for (;;) {
-            Index<K,V> q = head;
-            Index<K,V> r = q.right;
-            for (;;) {
+            for (Index<K,V> q = head, r = q.right, d;;) {
                 if (r != null) {
                     Node<K,V> n = r.node;
                     K k = n.key;
@@ -724,18 +675,16 @@
                         r = q.right;         // reread r
                         continue;
                     }
-                    if (key.compareTo(k) > 0) {
+                    if (cpr(cmp, key, k) > 0) {
                         q = r;
                         r = r.right;
                         continue;
                     }
                 }
-                Index<K,V> d = q.down;
-                if (d != null) {
-                    q = d;
-                    r = d.right;
-                } else
+                if ((d = q.down) == null)
                     return q.node;
+                q = d;
+                r = d.right;
             }
         }
     }
@@ -784,54 +733,71 @@
      * @param key the key
      * @return node holding key, or null if no such
      */
-    private Node<K,V> findNode(Comparable<? super K> key) {
-        for (;;) {
-            Node<K,V> b = findPredecessor(key);
-            Node<K,V> n = b.next;
-            for (;;) {
+    private Node<K,V> findNode(Object key) {
+        if (key == null)
+            throw new NullPointerException(); // don't postpone errors
+        Comparator<? super K> cmp = comparator;
+        outer: for (;;) {
+            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
+                Object v; int c;
                 if (n == null)
-                    return null;
+                    break outer;
                 Node<K,V> f = n.next;
                 if (n != b.next)                // inconsistent read
                     break;
-                Object v = n.value;
-                if (v == null) {                // n is deleted
+                if ((v = n.value) == null) {    // n is deleted
                     n.helpDelete(b, f);
                     break;
                 }
-                if (v == n || b.value == null)  // b is deleted
+                if (b.value == null || v == n)  // b is deleted
                     break;
-                int c = key.compareTo(n.key);
-                if (c == 0)
+                if ((c = cpr(cmp, key, n.key)) == 0)
                     return n;
                 if (c < 0)
-                    return null;
+                    break outer;
                 b = n;
                 n = f;
             }
         }
+        return null;
     }
 
     /**
-     * Gets value for key using findNode.
-     * @param okey the key
+     * Gets value for key. Almost the same as findNode, but returns
+     * the found value (to avoid retries during re-reads)
+     *
+     * @param key the key
      * @return the value, or null if absent
      */
-    private V doGet(Object okey) {
-        Comparable<? super K> key = comparable(okey);
-        /*
-         * 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;
+    private V doGet(Object key) {
+        if (key == null)
+            throw new NullPointerException();
+        Comparator<? super K> cmp = comparator;
+        outer: for (;;) {
+            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
+                Object v; int c;
+                if (n == null)
+                    break outer;
+                Node<K,V> f = n.next;
+                if (n != b.next)                // inconsistent read
+                    break;
+                if ((v = n.value) == null) {    // n is deleted
+                    n.helpDelete(b, f);
+                    break;
+                }
+                if (b.value == null || v == n)  // b is deleted
+                    break;
+                if ((c = cpr(cmp, key, n.key)) == 0) {
+                    @SuppressWarnings("unchecked") V vv = (V)v;
+                    return vv;
+                }
+                if (c < 0)
+                    break outer;
+                b = n;
+                n = f;
+            }
         }
+        return null;
     }
 
     /* ---------------- Insertion -------------- */
@@ -839,187 +805,126 @@
     /**
      * 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 key 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<? super K> key = comparable(kkey);
-        for (;;) {
-            Node<K,V> b = findPredecessor(key);
-            Node<K,V> n = b.next;
-            for (;;) {
+    private V doPut(K key, V value, boolean onlyIfAbsent) {
+        Node<K,V> z;             // added node
+        if (key == null)
+            throw new NullPointerException();
+        Comparator<? super K> cmp = comparator;
+        outer: for (;;) {
+            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
                 if (n != null) {
+                    Object v; int c;
                     Node<K,V> f = n.next;
                     if (n != b.next)               // inconsistent read
                         break;
-                    Object v = n.value;
-                    if (v == null) {               // n is deleted
+                    if ((v = n.value) == null) {   // n is deleted
                         n.helpDelete(b, f);
                         break;
                     }
-                    if (v == n || b.value == null) // b is deleted
+                    if (b.value == null || v == n) // b is deleted
                         break;
-                    int c = key.compareTo(n.key);
-                    if (c > 0) {
+                    if ((c = cpr(cmp, key, n.key)) > 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
+                        if (onlyIfAbsent || n.casValue(v, value)) {
+                            @SuppressWarnings("unchecked") V vv = (V)v;
+                            return vv;
+                        }
+                        break; // restart if lost race to replace value
                     }
                     // else c < 0; fall through
                 }
 
-                Node<K,V> z = new Node<K,V>(kkey, value, n);
+                z = new Node<K,V>(key, 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;
+                break outer;
             }
         }
-    }
 
-    /**
-     * Returns a random level for inserting a new node.
-     * Hardwired to k=1, p=0.5, max 31 (see above and
-     * Pugh's "Skip List Cookbook", sec 3.4).
-     *
-     * This uses the simplest of the generators described in George
-     * Marsaglia's "Xorshift RNGs" paper.  This is not a high-quality
-     * generator but is acceptable here.
-     */
-    private int randomLevel() {
-        int x = randomSeed;
-        x ^= x << 13;
-        x ^= x >>> 17;
-        randomSeed = x ^= x << 5;
-        if ((x & 0x80000001) != 0) // test highest and lowest bits
-            return 0;
-        int level = 1;
-        while (((x >>>= 1) & 1) != 0) ++level;
-        return level;
-    }
-
-    /**
-     * Creates and adds index nodes for the 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) {
+        int rnd = ThreadLocalRandom.nextSecondarySeed();
+        if ((rnd & 0x80000001) == 0) { // test highest and lowest bits
+            int level = 1, max;
+            while (((rnd >>>= 1) & 1) != 0)
+                ++level;
             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;
+            HeadIndex<K,V> h = head;
+            if (level <= (max = h.level)) {
+                for (int i = 1; i <= level; ++i)
+                    idx = new Index<K,V>(z, idx, null);
+            }
+            else { // try to grow by one level
+                level = max + 1; // hold in array and later pick the one to use
+                @SuppressWarnings("unchecked")Index<K,V>[] idxs =
+                    (Index<K,V>[])new Index<?,?>[level+1];
+                for (int i = 1; i <= level; ++i)
+                    idxs[i] = idx = new Index<K,V>(z, idx, null);
+                for (;;) {
+                    h = head;
+                    int oldLevel = h.level;
+                    if (level <= oldLevel) // lost race to add level
+                        break;
+                    HeadIndex<K,V> newh = h;
+                    Node<K,V> oldbase = h.node;
+                    for (int j = oldLevel+1; j <= level; ++j)
+                        newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
+                    if (casHead(h, newh)) {
+                        h = newh;
+                        idx = idxs[level = oldLevel];
+                        break;
+                    }
                 }
             }
-            addIndex(idxs[k], oldh, k);
-        }
-    }
-
-    /**
-     * Adds 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<? super K> key = comparable(idx.node.key);
-        if (key == null) throw new NullPointerException();
+            // find insertion points and splice in
+            splice: for (int insertionLevel = level;;) {
+                int j = h.level;
+                for (Index<K,V> q = h, r = q.right, t = idx;;) {
+                    if (q == null || t == null)
+                        break splice;
+                    if (r != null) {
+                        Node<K,V> n = r.node;
+                        // compare before deletion check avoids needing recheck
+                        int c = cpr(cmp, key, n.key);
+                        if (n.value == null) {
+                            if (!q.unlink(r))
+                                break;
+                            r = q.right;
+                            continue;
+                        }
+                        if (c > 0) {
+                            q = r;
+                            r = r.right;
+                            continue;
+                        }
+                    }
 
-        // Similar to findPredecessor, but adding index nodes along
-        // path to key.
-        for (;;) {
-            int j = h.level;
-            Index<K,V> q = h;
-            Index<K,V> r = q.right;
-            Index<K,V> t = idx;
-            for (;;) {
-                if (r != null) {
-                    Node<K,V> n = r.node;
-                    // compare before deletion check avoids needing recheck
-                    int c = key.compareTo(n.key);
-                    if (n.value == null) {
-                        if (!q.unlink(r))
-                            break;
-                        r = q.right;
-                        continue;
-                    }
-                    if (c > 0) {
-                        q = r;
-                        r = r.right;
-                        continue;
+                    if (j == insertionLevel) {
+                        if (!q.link(r, t))
+                            break; // restart
+                        if (t.node.value == null) {
+                            findNode(key);
+                            break splice;
+                        }
+                        if (--insertionLevel == 0)
+                            break splice;
                     }
+
+                    if (--j >= insertionLevel && j < level)
+                        t = t.down;
+                    q = q.down;
+                    r = q.right;
                 }
-
-                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;
-                r = q.right;
             }
         }
+        return null;
     }
 
     /* ---------------- Deletion -------------- */
@@ -1038,51 +943,52 @@
      * search for it, and we'd like to ensure lack of garbage
      * retention, so must call to be sure.
      *
-     * @param okey the key
+     * @param key the key
      * @param value if non-null, the value that must be
      * associated with key
      * @return the node, or null if not found
      */
-    final V doRemove(Object okey, Object value) {
-        Comparable<? super K> key = comparable(okey);
-        for (;;) {
-            Node<K,V> b = findPredecessor(key);
-            Node<K,V> n = b.next;
-            for (;;) {
+    final V doRemove(Object key, Object value) {
+        if (key == null)
+            throw new NullPointerException();
+        Comparator<? super K> cmp = comparator;
+        outer: for (;;) {
+            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
+                Object v; int c;
                 if (n == null)
-                    return null;
+                    break outer;
                 Node<K,V> f = n.next;
                 if (n != b.next)                    // inconsistent read
                     break;
-                Object v = n.value;
-                if (v == null) {                    // n is deleted
+                if ((v = n.value) == null) {        // n is deleted
                     n.helpDelete(b, f);
                     break;
                 }
-                if (v == n || b.value == null)      // b is deleted
+                if (b.value == null || v == n)      // b is deleted
                     break;
-                int c = key.compareTo(n.key);
-                if (c < 0)
-                    return null;
+                if ((c = cpr(cmp, key, n.key)) < 0)
+                    break outer;
                 if (c > 0) {
                     b = n;
                     n = f;
                     continue;
                 }
                 if (value != null && !value.equals(v))
-                    return null;
+                    break outer;
                 if (!n.casValue(v, null))
                     break;
                 if (!n.appendMarker(f) || !b.casNext(n, f))
-                    findNode(key);                  // Retry via findNode
+                    findNode(key);                  // retry via findNode
                 else {
-                    findPredecessor(key);           // Clean index
+                    findPredecessor(key, cmp);      // clean index
                     if (head.right == null)
                         tryReduceLevel();
                 }
-                return (V)v;
+                @SuppressWarnings("unchecked") V vv = (V)v;
+                return vv;
             }
         }
+        return null;
     }
 
     /**
@@ -1126,11 +1032,9 @@
      * 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)
+    final Node<K,V> findFirst() {
+        for (Node<K,V> b, n;;) {
+            if ((n = (b = head.node).next) == null)
                 return null;
             if (n.value != null)
                 return n;
@@ -1142,11 +1046,9 @@
      * Removes first entry; returns its snapshot.
      * @return null if empty, else snapshot of first entry
      */
-    Map.Entry<K,V> doRemoveFirstEntry() {
-        for (;;) {
-            Node<K,V> b = head.node;
-            Node<K,V> n = b.next;
-            if (n == null)
+    private Map.Entry<K,V> doRemoveFirstEntry() {
+        for (Node<K,V> b, n;;) {
+            if ((n = (b = head.node).next) == null)
                 return null;
             Node<K,V> f = n.next;
             if (n != b.next)
@@ -1161,7 +1063,8 @@
             if (!n.appendMarker(f) || !b.casNext(n, f))
                 findFirst(); // retry
             clearIndexToFirst();
-            return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, (V)v);
+            @SuppressWarnings("unchecked") V vv = (V)v;
+            return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, vv);
         }
     }
 
@@ -1170,8 +1073,7 @@
      */
     private void clearIndexToFirst() {
         for (;;) {
-            Index<K,V> q = head;
-            for (;;) {
+            for (Index<K,V> q = head;;) {
                 Index<K,V> r = q.right;
                 if (r != null && r.indexesDeletedNode() && !q.unlink(r))
                     break;
@@ -1184,6 +1086,52 @@
         }
     }
 
+    /**
+     * Removes last entry; returns its snapshot.
+     * Specialized variant of doRemove.
+     * @return null if empty, else snapshot of last entry
+     */
+    private Map.Entry<K,V> doRemoveLastEntry() {
+        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 (b.value == null || v == n)      // b is deleted
+                    break;
+                if (f != null) {
+                    b = n;
+                    n = f;
+                    continue;
+                }
+                if (!n.casValue(v, null))
+                    break;
+                K key = n.key;
+                if (!n.appendMarker(f) || !b.casNext(n, f))
+                    findNode(key);                  // retry via findNode
+                else {                              // clean index
+                    findPredecessor(key, comparator);
+                    if (head.right == null)
+                        tryReduceLevel();
+                }
+                @SuppressWarnings("unchecked") V vv = (V)v;
+                return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
+            }
+        }
+    }
 
     /* ---------------- Finding and removing last element -------------- */
 
@@ -1191,7 +1139,7 @@
      * Specialized version of find to get last valid node.
      * @return last node or null if empty
      */
-    Node<K,V> findLast() {
+    final Node<K,V> findLast() {
         /*
          * findPredecessor can't be used to traverse index level
          * because this doesn't use comparisons.  So traversals of
@@ -1210,9 +1158,7 @@
             } else if ((d = q.down) != null) {
                 q = d;
             } else {
-                Node<K,V> b = q.node;
-                Node<K,V> n = b.next;
-                for (;;) {
+                for (Node<K,V> b = q.node, n = b.next;;) {
                     if (n == null)
                         return b.isBaseHeader() ? null : b;
                     Node<K,V> f = n.next;            // inconsistent read
@@ -1223,7 +1169,7 @@
                         n.helpDelete(b, f);
                         break;
                     }
-                    if (v == n || b.value == null)   // b is deleted
+                    if (b.value == null || v == n)      // b is deleted
                         break;
                     b = n;
                     n = f;
@@ -1242,8 +1188,7 @@
      */
     private Node<K,V> findPredecessorOfLast() {
         for (;;) {
-            Index<K,V> q = head;
-            for (;;) {
+            for (Index<K,V> q = head;;) {
                 Index<K,V> d, r;
                 if ((r = q.right) != null) {
                     if (r.indexesDeletedNode()) {
@@ -1264,53 +1209,6 @@
         }
     }
 
-    /**
-     * Removes last entry; returns its snapshot.
-     * Specialized variant of doRemove.
-     * @return null if empty, else snapshot of last entry
-     */
-    Map.Entry<K,V> doRemoveLastEntry() {
-        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<? super 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 new AbstractMap.SimpleImmutableEntry<K,V>(key, (V)v);
-            }
-        }
-    }
-
     /* ---------------- Relational operations -------------- */
 
     // Control values OR'ed as arguments to findNear
@@ -1321,29 +1219,28 @@
 
     /**
      * Utility for ceiling, floor, lower, higher methods.
-     * @param kkey the key
+     * @param key 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<? super K> key = comparable(kkey);
+    final Node<K,V> findNear(K key, int rel, Comparator<? super K> cmp) {
+        if (key == null)
+            throw new NullPointerException();
         for (;;) {
-            Node<K,V> b = findPredecessor(key);
-            Node<K,V> n = b.next;
-            for (;;) {
+            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
+                Object v;
                 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
+                if ((v = n.value) == null) {      // n is deleted
                     n.helpDelete(b, f);
                     break;
                 }
-                if (v == n || b.value == null)    // b is deleted
+                if (b.value == null || v == n)      // b is deleted
                     break;
-                int c = key.compareTo(n.key);
+                int c = cpr(cmp, key, n.key);
                 if ((c == 0 && (rel & EQ) != 0) ||
                     (c <  0 && (rel & LT) == 0))
                     return n;
@@ -1361,9 +1258,10 @@
      * @param rel the relation -- OR'ed combination of EQ, LT, GT
      * @return Entry fitting relation, or null if no such
      */
-    AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
+    final AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
+        Comparator<? super K> cmp = comparator;
         for (;;) {
-            Node<K,V> n = findNear(key, rel);
+            Node<K,V> n = findNear(key, rel, cmp);
             if (n == null)
                 return null;
             AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
@@ -1372,7 +1270,6 @@
         }
     }
 
-
     /* ---------------- Constructors -------------- */
 
     /**
@@ -1389,7 +1286,7 @@
      * comparator.
      *
      * @param comparator the comparator that will be used to order this map.
-     *        If <tt>null</tt>, the {@linkplain Comparable natural
+     *        If {@code null}, the {@linkplain Comparable natural
      *        ordering} of the keys will be used.
      */
     public ConcurrentSkipListMap(Comparator<? super K> comparator) {
@@ -1403,7 +1300,7 @@
      * the keys.
      *
      * @param  m the map whose mappings are to be placed in this map
-     * @throws ClassCastException if the keys in <tt>m</tt> are not
+     * @throws ClassCastException if the keys in {@code m} are not
      *         {@link Comparable}, or are not mutually comparable
      * @throws NullPointerException if the specified map or any of its keys
      *         or values are null
@@ -1430,7 +1327,7 @@
     }
 
     /**
-     * Returns a shallow copy of this <tt>ConcurrentSkipListMap</tt>
+     * Returns a shallow copy of this {@code ConcurrentSkipListMap}
      * instance. (The keys and values themselves are not cloned.)
      *
      * @return a shallow copy of this map
@@ -1477,8 +1374,14 @@
             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;
+            int rnd = ThreadLocalRandom.current().nextInt();
+            int j = 0;
+            if ((rnd & 0x80000001) == 0) {
+                do {
+                    ++j;
+                } while (((rnd >>>= 1) & 1) != 0);
+                if (j > h.level) j = h.level + 1;
+            }
             K k = e.getKey();
             V v = e.getValue();
             if (k == null || v == null)
@@ -1511,7 +1414,7 @@
      *
      * @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
+     * {@code null}. The key-value mappings are emitted in key-order
      * (as determined by the Comparator, or by the keys' natural
      * ordering if no Comparator).
      */
@@ -1534,6 +1437,7 @@
     /**
      * Reconstitutes this map from a stream (that is, deserializes it).
      */
+    @SuppressWarnings("unchecked")
     private void readObject(final java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         // Read in the Comparator and any hidden stuff
@@ -1569,8 +1473,14 @@
                 throw new NullPointerException();
             K key = (K) k;
             V val = (V) v;
-            int j = randomLevel();
-            if (j > h.level) j = h.level + 1;
+            int rnd = ThreadLocalRandom.current().nextInt();
+            int j = 0;
+            if ((rnd & 0x80000001) == 0) {
+                do {
+                    ++j;
+                } while (((rnd >>>= 1) & 1) != 0);
+                if (j > h.level) j = h.level + 1;
+            }
             Node<K,V> z = new Node<K,V>(key, val, null);
             basepred.next = z;
             basepred = z;
@@ -1595,11 +1505,11 @@
     /* ------ Map API methods ------ */
 
     /**
-     * Returns <tt>true</tt> if this map contains a mapping for the specified
+     * Returns {@code true} 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
+     * @return {@code true} if this map contains a mapping for the specified key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key is null
@@ -1627,6 +1537,22 @@
     }
 
     /**
+     * Returns the value to which the specified key is mapped,
+     * or the given defaultValue if this map contains no mapping for the key.
+     *
+     * @param key the key
+     * @param defaultValue the value to return if this map contains
+     * no mapping for the given key
+     * @return the mapping for the key, if present; else the defaultValue
+     * @throws NullPointerException if the specified key is null
+     * @since 1.8
+     */
+    public V getOrDefault(Object key, V defaultValue) {
+        V v;
+        return (v = doGet(key)) == null ? defaultValue : v;
+    }
+
+    /**
      * Associates the specified value with the specified key in this map.
      * If the map previously contained a mapping for the key, the old
      * value is replaced.
@@ -1634,7 +1560,7 @@
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
-     *         <tt>null</tt> if there was no mapping for the key
+     *         {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key or value is null
@@ -1650,7 +1576,7 @@
      *
      * @param  key key for which mapping should be removed
      * @return the previous value associated with the specified key, or
-     *         <tt>null</tt> if there was no mapping for the key
+     *         {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key is null
@@ -1660,15 +1586,15 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map maps one or more keys to the
+     * Returns {@code true} if this map maps one or more keys to the
      * specified value.  This operation requires time linear in the
      * map size. Additionally, it is possible for the map to change
      * during execution of this method, in which case the returned
      * result may be inaccurate.
      *
      * @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
+     * @return {@code true} if a mapping to {@code value} exists;
+     *         {@code false} otherwise
      * @throws NullPointerException if the specified value is null
      */
     public boolean containsValue(Object value) {
@@ -1684,8 +1610,8 @@
 
     /**
      * Returns the number of key-value mappings in this map.  If this map
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
-     * returns <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, it
+     * returns {@code Integer.MAX_VALUE}.
      *
      * <p>Beware that, unlike in most collections, this method is
      * <em>NOT</em> a constant-time operation. Because of the
@@ -1708,8 +1634,8 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map contains no key-value mappings.
-     * @return <tt>true</tt> if this map contains no key-value mappings
+     * Returns {@code true} if this map contains no key-value mappings.
+     * @return {@code true} if this map contains no key-value mappings
      */
     public boolean isEmpty() {
         return findFirst() == null;
@@ -1722,6 +1648,140 @@
         initialize();
     }
 
+    /**
+     * If the specified key is not already associated with a value,
+     * attempts to compute its value using the given mapping function
+     * and enters it into this map unless {@code null}.  The function
+     * is <em>NOT</em> guaranteed to be applied once atomically only
+     * if the value is not present.
+     *
+     * @param key key with which the specified value is to be associated
+     * @param mappingFunction the function to compute a value
+     * @return the current (existing or computed) value associated with
+     *         the specified key, or null if the computed value is null
+     * @throws NullPointerException if the specified key is null
+     *         or the mappingFunction is null
+     * @since 1.8
+     */
+    public V computeIfAbsent(K key,
+                             Function<? super K, ? extends V> mappingFunction) {
+        if (key == null || mappingFunction == null)
+            throw new NullPointerException();
+        V v, p, r;
+        if ((v = doGet(key)) == null &&
+            (r = mappingFunction.apply(key)) != null)
+            v = (p = doPut(key, r, true)) == null ? r : p;
+        return v;
+    }
+
+    /**
+     * If the value for the specified key is present, attempts to
+     * compute a new mapping given the key and its current mapped
+     * value. The function is <em>NOT</em> guaranteed to be applied
+     * once atomically.
+     *
+     * @param key key with which a value may be associated
+     * @param remappingFunction the function to compute a value
+     * @return the new value associated with the specified key, or null if none
+     * @throws NullPointerException if the specified key is null
+     *         or the remappingFunction is null
+     * @since 1.8
+     */
+    public V computeIfPresent(K key,
+                              BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        if (key == null || remappingFunction == null)
+            throw new NullPointerException();
+        Node<K,V> n; Object v;
+        while ((n = findNode(key)) != null) {
+            if ((v = n.value) != null) {
+                @SuppressWarnings("unchecked") V vv = (V) v;
+                V r = remappingFunction.apply(key, vv);
+                if (r != null) {
+                    if (n.casValue(vv, r))
+                        return r;
+                }
+                else if (doRemove(key, vv) != null)
+                    break;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Attempts to compute a mapping for the specified key and its
+     * current mapped value (or {@code null} if there is no current
+     * mapping). The function is <em>NOT</em> guaranteed to be applied
+     * once atomically.
+     *
+     * @param key key with which the specified value is to be associated
+     * @param remappingFunction the function to compute a value
+     * @return the new value associated with the specified key, or null if none
+     * @throws NullPointerException if the specified key is null
+     *         or the remappingFunction is null
+     * @since 1.8
+     */
+    public V compute(K key,
+                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        if (key == null || remappingFunction == null)
+            throw new NullPointerException();
+        for (;;) {
+            Node<K,V> n; Object v; V r;
+            if ((n = findNode(key)) == null) {
+                if ((r = remappingFunction.apply(key, null)) == null)
+                    break;
+                if (doPut(key, r, true) == null)
+                    return r;
+            }
+            else if ((v = n.value) != null) {
+                @SuppressWarnings("unchecked") V vv = (V) v;
+                if ((r = remappingFunction.apply(key, vv)) != null) {
+                    if (n.casValue(vv, r))
+                        return r;
+                }
+                else if (doRemove(key, vv) != null)
+                    break;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * If the specified key is not already associated with a value,
+     * associates it with the given value.  Otherwise, replaces the
+     * value with the results of the given remapping function, or
+     * removes if {@code null}. The function is <em>NOT</em>
+     * guaranteed to be applied once atomically.
+     *
+     * @param key key with which the specified value is to be associated
+     * @param value the value to use if absent
+     * @param remappingFunction the function to recompute a value if present
+     * @return the new value associated with the specified key, or null if none
+     * @throws NullPointerException if the specified key or value is null
+     *         or the remappingFunction is null
+     * @since 1.8
+     */
+    public V merge(K key, V value,
+                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+        if (key == null || value == null || remappingFunction == null)
+            throw new NullPointerException();
+        for (;;) {
+            Node<K,V> n; Object v; V r;
+            if ((n = findNode(key)) == null) {
+                if (doPut(key, value, true) == null)
+                    return value;
+            }
+            else if ((v = n.value) != null) {
+                @SuppressWarnings("unchecked") V vv = (V) v;
+                if ((r = remappingFunction.apply(vv, value)) != null) {
+                    if (n.casValue(vv, r))
+                        return r;
+                }
+                else if (doRemove(key, vv) != null)
+                    return null;
+            }
+        }
+    }
+
     /* ---------------- View methods -------------- */
 
     /*
@@ -1744,11 +1804,11 @@
      * operations.  It does not support the {@code add} or {@code addAll}
      * operations.
      *
-     * <p>The view's {@code iterator} is a "weakly consistent" iterator
-     * that will never throw {@link 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.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * 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.
      *
      * <p>This method is equivalent to method {@code navigableKeySet}.
      *
@@ -1771,16 +1831,16 @@
      * 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.
+     * mapping from the map, via the {@code Iterator.remove},
+     * {@code Collection.remove}, {@code removeAll},
+     * {@code retainAll} and {@code clear} operations.  It does not
+     * support the {@code add} or {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
-     * that will never throw {@link 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.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * 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.
      */
     public Collection<V> values() {
         Values<V> vs = values;
@@ -1793,20 +1853,20 @@
      * 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 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.
+     * via the {@code Iterator.remove}, {@code Set.remove},
+     * {@code removeAll}, {@code retainAll} and {@code clear}
+     * operations.  It does not support the {@code add} or
+     * {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
-     * that will never throw {@link 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.
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * 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.
      *
-     * <p>The <tt>Map.Entry</tt> elements returned by
-     * <tt>iterator.next()</tt> do <em>not</em> support the
-     * <tt>setValue</tt> operation.
+     * <p>The {@code Map.Entry} elements returned by
+     * {@code iterator.next()} do <em>not</em> support the
+     * {@code setValue} operation.
      *
      * @return a set view of the mappings contained in this map,
      *         sorted in ascending key order
@@ -1830,15 +1890,15 @@
 
     /**
      * Compares the specified object with this map for equality.
-     * Returns <tt>true</tt> if the given object is also a map and the
+     * Returns {@code true} if the given object is also a map and the
      * two maps represent the same mappings.  More formally, two maps
-     * <tt>m1</tt> and <tt>m2</tt> represent the same mappings if
-     * <tt>m1.entrySet().equals(m2.entrySet())</tt>.  This
+     * {@code m1} and {@code m2} represent the same mappings if
+     * {@code m1.entrySet().equals(m2.entrySet())}.  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
+     * @return {@code true} if the specified object is equal to this map
      */
     public boolean equals(Object o) {
         if (o == this)
@@ -1870,7 +1930,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key or value is null
@@ -1891,9 +1951,7 @@
     public boolean remove(Object key, Object value) {
         if (key == null)
             throw new NullPointerException();
-        if (value == null)
-            return false;
-        return doRemove(key, value) != null;
+        return value != null && doRemove(key, value) != null;
     }
 
     /**
@@ -1904,15 +1962,13 @@
      * @throws NullPointerException if any of the arguments are null
      */
     public boolean replace(K key, V oldValue, V newValue) {
-        if (oldValue == null || newValue == null)
+        if (key == null || oldValue == null || newValue == null)
             throw new NullPointerException();
-        Comparable<? super K> k = comparable(key);
         for (;;) {
-            Node<K,V> n = findNode(k);
-            if (n == null)
+            Node<K,V> n; Object v;
+            if ((n = findNode(key)) == null)
                 return false;
-            Object v = n.value;
-            if (v != null) {
+            if ((v = n.value) != null) {
                 if (!oldValue.equals(v))
                     return false;
                 if (n.casValue(v, newValue))
@@ -1925,22 +1981,22 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key or value is null
      */
     public V replace(K key, V value) {
-        if (value == null)
+        if (key == null || value == null)
             throw new NullPointerException();
-        Comparable<? super K> k = comparable(key);
         for (;;) {
-            Node<K,V> n = findNode(k);
-            if (n == null)
+            Node<K,V> n; Object v;
+            if ((n = findNode(key)) == null)
                 return null;
-            Object v = n.value;
-            if (v != null && n.casValue(v, value))
-                return (V)v;
+            if ((v = n.value) != null && n.casValue(v, value)) {
+                @SuppressWarnings("unchecked") V vv = (V)v;
+                return vv;
+            }
         }
     }
 
@@ -2042,9 +2098,9 @@
 
     /**
      * Returns a key-value mapping associated with the greatest key
-     * strictly less than the given key, or <tt>null</tt> if there is
+     * strictly less than the given key, or {@code null} if there is
      * no such key. The returned entry does <em>not</em> support the
-     * <tt>Entry.setValue</tt> method.
+     * {@code Entry.setValue} method.
      *
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException if the specified key is null
@@ -2058,15 +2114,15 @@
      * @throws NullPointerException if the specified key is null
      */
     public K lowerKey(K key) {
-        Node<K,V> n = findNear(key, LT);
+        Node<K,V> n = findNear(key, LT, comparator);
         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
+     * less than or equal to the given key, or {@code null} if there
      * is no such key. The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      *
      * @param key the key
      * @throws ClassCastException {@inheritDoc}
@@ -2082,15 +2138,15 @@
      * @throws NullPointerException if the specified key is null
      */
     public K floorKey(K key) {
-        Node<K,V> n = findNear(key, LT|EQ);
+        Node<K,V> n = findNear(key, LT|EQ, comparator);
         return (n == null) ? null : n.key;
     }
 
     /**
      * Returns a key-value mapping associated with the least key
-     * greater than or equal to the given key, or <tt>null</tt> if
+     * greater than or equal to the given key, or {@code null} if
      * there is no such entry. The returned entry does <em>not</em>
-     * support the <tt>Entry.setValue</tt> method.
+     * support the {@code Entry.setValue} method.
      *
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException if the specified key is null
@@ -2104,15 +2160,15 @@
      * @throws NullPointerException if the specified key is null
      */
     public K ceilingKey(K key) {
-        Node<K,V> n = findNear(key, GT|EQ);
+        Node<K,V> n = findNear(key, GT|EQ, comparator);
         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
+     * strictly greater than the given key, or {@code null} if there
      * is no such key. The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      *
      * @param key the key
      * @throws ClassCastException {@inheritDoc}
@@ -2128,15 +2184,15 @@
      * @throws NullPointerException if the specified key is null
      */
     public K higherKey(K key) {
-        Node<K,V> n = findNear(key, GT);
+        Node<K,V> n = findNear(key, GT, comparator);
         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.
+     * key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> firstEntry() {
         for (;;) {
@@ -2151,9 +2207,9 @@
 
     /**
      * Returns a key-value mapping associated with the greatest
-     * key in this map, or <tt>null</tt> if the map is empty.
+     * key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> lastEntry() {
         for (;;) {
@@ -2168,9 +2224,9 @@
 
     /**
      * 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 least key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> pollFirstEntry() {
         return doRemoveFirstEntry();
@@ -2178,9 +2234,9 @@
 
     /**
      * 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 greatest key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> pollLastEntry() {
         return doRemoveLastEntry();
@@ -2202,13 +2258,11 @@
 
         /** Initializes ascending iterator for entire range. */
         Iter() {
-            for (;;) {
-                next = findFirst();
-                if (next == null)
-                    break;
+            while ((next = findFirst()) != null) {
                 Object x = next.value;
                 if (x != null && x != next) {
-                    nextValue = (V) x;
+                    @SuppressWarnings("unchecked") V vv = (V)x;
+                    nextValue = vv;
                     break;
                 }
             }
@@ -2223,13 +2277,11 @@
             if (next == null)
                 throw new NoSuchElementException();
             lastReturned = next;
-            for (;;) {
-                next = next.next;
-                if (next == null)
-                    break;
+            while ((next = next.next) != null) {
                 Object x = next.value;
                 if (x != null && x != next) {
-                    nextValue = (V) x;
+                    @SuppressWarnings("unchecked") V vv = (V)x;
+                    nextValue = vv;
                     break;
                 }
             }
@@ -2296,7 +2348,7 @@
 
     static final <E> List<E> toList(Collection<E> c) {
         // Using size() here would be a pessimization.
-        List<E> list = new ArrayList<E>();
+        ArrayList<E> list = new ArrayList<E>();
         for (E e : c)
             list.add(e);
         return list;
@@ -2304,7 +2356,7 @@
 
     static final class KeySet<E>
             extends AbstractSet<E> implements NavigableSet<E> {
-        private final ConcurrentNavigableMap<E,?> m;
+        final ConcurrentNavigableMap<E,?> m;
         KeySet(ConcurrentNavigableMap<E,?> map) { m = map; }
         public int size() { return m.size(); }
         public boolean isEmpty() { return m.isEmpty(); }
@@ -2326,6 +2378,7 @@
             Map.Entry<E,?> e = m.pollLastEntry();
             return (e == null) ? null : e.getKey();
         }
+        @SuppressWarnings("unchecked")
         public Iterator<E> iterator() {
             if (m instanceof ConcurrentSkipListMap)
                 return ((ConcurrentSkipListMap<E,Object>)m).keyIterator();
@@ -2376,13 +2429,21 @@
         public NavigableSet<E> descendingSet() {
             return new KeySet<E>(m.descendingMap());
         }
+        @SuppressWarnings("unchecked")
+        public Spliterator<E> spliterator() {
+            if (m instanceof ConcurrentSkipListMap)
+                return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
+            else
+                return (Spliterator<E>)((SubMap<E,?>)m).keyIterator();
+        }
     }
 
     static final class Values<E> extends AbstractCollection<E> {
-        private final ConcurrentNavigableMap<?, E> m;
+        final ConcurrentNavigableMap<?, E> m;
         Values(ConcurrentNavigableMap<?, E> map) {
             m = map;
         }
+        @SuppressWarnings("unchecked")
         public Iterator<E> iterator() {
             if (m instanceof ConcurrentSkipListMap)
                 return ((ConcurrentSkipListMap<?,E>)m).valueIterator();
@@ -2403,14 +2464,21 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+        @SuppressWarnings("unchecked")
+        public Spliterator<E> spliterator() {
+            if (m instanceof ConcurrentSkipListMap)
+                return ((ConcurrentSkipListMap<?,E>)m).valueSpliterator();
+            else
+                return (Spliterator<E>)((SubMap<?,E>)m).valueIterator();
+        }
     }
 
     static final class EntrySet<K1,V1> extends AbstractSet<Map.Entry<K1,V1>> {
-        private final ConcurrentNavigableMap<K1, V1> m;
+        final ConcurrentNavigableMap<K1, V1> m;
         EntrySet(ConcurrentNavigableMap<K1, V1> map) {
             m = map;
         }
-
+        @SuppressWarnings("unchecked")
         public Iterator<Map.Entry<K1,V1>> iterator() {
             if (m instanceof ConcurrentSkipListMap)
                 return ((ConcurrentSkipListMap<K1,V1>)m).entryIterator();
@@ -2457,6 +2525,14 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+        @SuppressWarnings("unchecked")
+        public Spliterator<Map.Entry<K1,V1>> spliterator() {
+            if (m instanceof ConcurrentSkipListMap)
+                return ((ConcurrentSkipListMap<K1,V1>)m).entrySpliterator();
+            else
+                return (Spliterator<Map.Entry<K1,V1>>)
+                    ((SubMap<K1,V1>)m).entryIterator();
+        }
     }
 
     /**
@@ -2466,8 +2542,8 @@
      * 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.
+     * constructed only using the {@code subMap}, {@code headMap}, and
+     * {@code tailMap} methods of their underlying maps.
      *
      * @serial include
      */
@@ -2495,14 +2571,15 @@
         private transient Collection<V> valuesView;
 
         /**
-         * Creates a new submap, initializing all fields
+         * Creates a new submap, initializing all fields.
          */
         SubMap(ConcurrentSkipListMap<K,V> map,
                K fromKey, boolean fromInclusive,
                K toKey, boolean toInclusive,
                boolean isDescending) {
+            Comparator<? super K> cmp = map.comparator;
             if (fromKey != null && toKey != null &&
-                map.compare(fromKey, toKey) > 0)
+                cpr(cmp, fromKey, toKey) > 0)
                 throw new IllegalArgumentException("inconsistent range");
             this.m = map;
             this.lo = fromKey;
@@ -2514,39 +2591,34 @@
 
         /* ----------------  Utilities -------------- */
 
-        private boolean tooLow(K key) {
-            if (lo != null) {
-                int c = m.compare(key, lo);
-                if (c < 0 || (c == 0 && !loInclusive))
-                    return true;
-            }
-            return false;
+        boolean tooLow(Object key, Comparator<? super K> cmp) {
+            int c;
+            return (lo != null && ((c = cpr(cmp, key, lo)) < 0 ||
+                                   (c == 0 && !loInclusive)));
         }
 
-        private boolean tooHigh(K key) {
-            if (hi != null) {
-                int c = m.compare(key, hi);
-                if (c > 0 || (c == 0 && !hiInclusive))
-                    return true;
-            }
-            return false;
+        boolean tooHigh(Object key, Comparator<? super K> cmp) {
+            int c;
+            return (hi != null && ((c = cpr(cmp, key, hi)) > 0 ||
+                                   (c == 0 && !hiInclusive)));
         }
 
-        private boolean inBounds(K key) {
-            return !tooLow(key) && !tooHigh(key);
+        boolean inBounds(Object key, Comparator<? super K> cmp) {
+            return !tooLow(key, cmp) && !tooHigh(key, cmp);
         }
 
-        private void checkKeyBounds(K key) throws IllegalArgumentException {
+        void checkKeyBounds(K key, Comparator<? super K> cmp) {
             if (key == null)
                 throw new NullPointerException();
-            if (!inBounds(key))
+            if (!inBounds(key, cmp))
                 throw new IllegalArgumentException("key out of range");
         }
 
         /**
-         * Returns true if node key is less than upper bound of range
+         * Returns true if node key is less than upper bound of range.
          */
-        private boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
+        boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n,
+                            Comparator<? super K> cmp) {
             if (n == null)
                 return false;
             if (hi == null)
@@ -2554,7 +2626,7 @@
             K k = n.key;
             if (k == null) // pass by markers and headers
                 return true;
-            int c = m.compare(k, hi);
+            int c = cpr(cmp, k, hi);
             if (c > 0 || (c == 0 && !hiInclusive))
                 return false;
             return true;
@@ -2562,58 +2634,61 @@
 
         /**
          * Returns lowest node. This node might not be in range, so
-         * most usages need to check bounds
+         * most usages need to check bounds.
          */
-        private ConcurrentSkipListMap.Node<K,V> loNode() {
+        ConcurrentSkipListMap.Node<K,V> loNode(Comparator<? super K> cmp) {
             if (lo == null)
                 return m.findFirst();
             else if (loInclusive)
-                return m.findNear(lo, GT|EQ);
+                return m.findNear(lo, GT|EQ, cmp);
             else
-                return m.findNear(lo, GT);
+                return m.findNear(lo, GT, cmp);
         }
 
         /**
          * Returns highest node. This node might not be in range, so
-         * most usages need to check bounds
+         * most usages need to check bounds.
          */
-        private ConcurrentSkipListMap.Node<K,V> hiNode() {
+        ConcurrentSkipListMap.Node<K,V> hiNode(Comparator<? super K> cmp) {
             if (hi == null)
                 return m.findLast();
             else if (hiInclusive)
-                return m.findNear(hi, LT|EQ);
+                return m.findNear(hi, LT|EQ, cmp);
             else
-                return m.findNear(hi, LT);
+                return m.findNear(hi, LT, cmp);
         }
 
         /**
-         * Returns lowest absolute key (ignoring directonality)
+         * Returns lowest absolute key (ignoring directonality).
          */
-        private K lowestKey() {
-            ConcurrentSkipListMap.Node<K,V> n = loNode();
-            if (isBeforeEnd(n))
+        K lowestKey() {
+            Comparator<? super K> cmp = m.comparator;
+            ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
+            if (isBeforeEnd(n, cmp))
                 return n.key;
             else
                 throw new NoSuchElementException();
         }
 
         /**
-         * Returns highest absolute key (ignoring directonality)
+         * Returns highest absolute key (ignoring directonality).
          */
-        private K highestKey() {
-            ConcurrentSkipListMap.Node<K,V> n = hiNode();
+        K highestKey() {
+            Comparator<? super K> cmp = m.comparator;
+            ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
             if (n != null) {
                 K last = n.key;
-                if (inBounds(last))
+                if (inBounds(last, cmp))
                     return last;
             }
             throw new NoSuchElementException();
         }
 
-        private Map.Entry<K,V> lowestEntry() {
+        Map.Entry<K,V> lowestEntry() {
+            Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                ConcurrentSkipListMap.Node<K,V> n = loNode();
-                if (!isBeforeEnd(n))
+                ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
+                if (!isBeforeEnd(n, cmp))
                     return null;
                 Map.Entry<K,V> e = n.createSnapshot();
                 if (e != null)
@@ -2621,10 +2696,11 @@
             }
         }
 
-        private Map.Entry<K,V> highestEntry() {
+        Map.Entry<K,V> highestEntry() {
+            Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                ConcurrentSkipListMap.Node<K,V> n = hiNode();
-                if (n == null || !inBounds(n.key))
+                ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
+                if (n == null || !inBounds(n.key, cmp))
                     return null;
                 Map.Entry<K,V> e = n.createSnapshot();
                 if (e != null)
@@ -2632,13 +2708,14 @@
             }
         }
 
-        private Map.Entry<K,V> removeLowest() {
+        Map.Entry<K,V> removeLowest() {
+            Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                Node<K,V> n = loNode();
+                Node<K,V> n = loNode(cmp);
                 if (n == null)
                     return null;
                 K k = n.key;
-                if (!inBounds(k))
+                if (!inBounds(k, cmp))
                     return null;
                 V v = m.doRemove(k, null);
                 if (v != null)
@@ -2646,13 +2723,14 @@
             }
         }
 
-        private Map.Entry<K,V> removeHighest() {
+        Map.Entry<K,V> removeHighest() {
+            Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                Node<K,V> n = hiNode();
+                Node<K,V> n = hiNode(cmp);
                 if (n == null)
                     return null;
                 K k = n.key;
-                if (!inBounds(k))
+                if (!inBounds(k, cmp))
                     return null;
                 V v = m.doRemove(k, null);
                 if (v != null)
@@ -2663,20 +2741,21 @@
         /**
          * Submap version of ConcurrentSkipListMap.getNearEntry
          */
-        private Map.Entry<K,V> getNearEntry(K key, int rel) {
+        Map.Entry<K,V> getNearEntry(K key, int rel) {
+            Comparator<? super K> cmp = m.comparator;
             if (isDescending) { // adjust relation for direction
                 if ((rel & LT) == 0)
                     rel |= LT;
                 else
                     rel &= ~LT;
             }
-            if (tooLow(key))
+            if (tooLow(key, cmp))
                 return ((rel & LT) != 0) ? null : lowestEntry();
-            if (tooHigh(key))
+            if (tooHigh(key, cmp))
                 return ((rel & LT) != 0) ? highestEntry() : null;
             for (;;) {
-                Node<K,V> n = m.findNear(key, rel);
-                if (n == null || !inBounds(n.key))
+                Node<K,V> n = m.findNear(key, rel, cmp);
+                if (n == null || !inBounds(n.key, cmp))
                     return null;
                 K k = n.key;
                 V v = n.getValidValue();
@@ -2686,35 +2765,36 @@
         }
 
         // Almost the same as getNearEntry, except for keys
-        private K getNearKey(K key, int rel) {
+        K getNearKey(K key, int rel) {
+            Comparator<? super K> cmp = m.comparator;
             if (isDescending) { // adjust relation for direction
                 if ((rel & LT) == 0)
                     rel |= LT;
                 else
                     rel &= ~LT;
             }
-            if (tooLow(key)) {
+            if (tooLow(key, cmp)) {
                 if ((rel & LT) == 0) {
-                    ConcurrentSkipListMap.Node<K,V> n = loNode();
-                    if (isBeforeEnd(n))
+                    ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
+                    if (isBeforeEnd(n, cmp))
                         return n.key;
                 }
                 return null;
             }
-            if (tooHigh(key)) {
+            if (tooHigh(key, cmp)) {
                 if ((rel & LT) != 0) {
-                    ConcurrentSkipListMap.Node<K,V> n = hiNode();
+                    ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
                     if (n != null) {
                         K last = n.key;
-                        if (inBounds(last))
+                        if (inBounds(last, cmp))
                             return last;
                     }
                 }
                 return null;
             }
             for (;;) {
-                Node<K,V> n = m.findNear(key, rel);
-                if (n == null || !inBounds(n.key))
+                Node<K,V> n = m.findNear(key, rel, cmp);
+                if (n == null || !inBounds(n.key, cmp))
                     return null;
                 K k = n.key;
                 V v = n.getValidValue();
@@ -2727,30 +2807,28 @@
 
         public boolean containsKey(Object key) {
             if (key == null) throw new NullPointerException();
-            K k = (K)key;
-            return inBounds(k) && m.containsKey(k);
+            return inBounds(key, m.comparator) && m.containsKey(key);
         }
 
         public V get(Object key) {
             if (key == null) throw new NullPointerException();
-            K k = (K)key;
-            return (!inBounds(k)) ? null : m.get(k);
+            return (!inBounds(key, m.comparator)) ? null : m.get(key);
         }
 
         public V put(K key, V value) {
-            checkKeyBounds(key);
+            checkKeyBounds(key, m.comparator);
             return m.put(key, value);
         }
 
         public V remove(Object key) {
-            K k = (K)key;
-            return (!inBounds(k)) ? null : m.remove(k);
+            return (!inBounds(key, m.comparator)) ? null : m.remove(key);
         }
 
         public int size() {
+            Comparator<? super K> cmp = m.comparator;
             long count = 0;
-            for (ConcurrentSkipListMap.Node<K,V> n = loNode();
-                 isBeforeEnd(n);
+            for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
+                 isBeforeEnd(n, cmp);
                  n = n.next) {
                 if (n.getValidValue() != null)
                     ++count;
@@ -2759,14 +2837,16 @@
         }
 
         public boolean isEmpty() {
-            return !isBeforeEnd(loNode());
+            Comparator<? super K> cmp = m.comparator;
+            return !isBeforeEnd(loNode(cmp), cmp);
         }
 
         public boolean containsValue(Object value) {
             if (value == null)
                 throw new NullPointerException();
-            for (ConcurrentSkipListMap.Node<K,V> n = loNode();
-                 isBeforeEnd(n);
+            Comparator<? super K> cmp = m.comparator;
+            for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
+                 isBeforeEnd(n, cmp);
                  n = n.next) {
                 V v = n.getValidValue();
                 if (v != null && value.equals(v))
@@ -2776,8 +2856,9 @@
         }
 
         public void clear() {
-            for (ConcurrentSkipListMap.Node<K,V> n = loNode();
-                 isBeforeEnd(n);
+            Comparator<? super K> cmp = m.comparator;
+            for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
+                 isBeforeEnd(n, cmp);
                  n = n.next) {
                 if (n.getValidValue() != null)
                     m.remove(n.key);
@@ -2787,22 +2868,21 @@
         /* ----------------  ConcurrentMap API methods -------------- */
 
         public V putIfAbsent(K key, V value) {
-            checkKeyBounds(key);
+            checkKeyBounds(key, m.comparator);
             return m.putIfAbsent(key, value);
         }
 
         public boolean remove(Object key, Object value) {
-            K k = (K)key;
-            return inBounds(k) && m.remove(k, value);
+            return inBounds(key, m.comparator) && m.remove(key, value);
         }
 
         public boolean replace(K key, V oldValue, V newValue) {
-            checkKeyBounds(key);
+            checkKeyBounds(key, m.comparator);
             return m.replace(key, oldValue, newValue);
         }
 
         public V replace(K key, V value) {
-            checkKeyBounds(key);
+            checkKeyBounds(key, m.comparator);
             return m.replace(key, value);
         }
 
@@ -2820,10 +2900,9 @@
          * Utility to create submaps, where given bounds override
          * unbounded(null) ones and/or are checked against bounded ones.
          */
-        private SubMap<K,V> newSubMap(K fromKey,
-                                      boolean fromInclusive,
-                                      K toKey,
-                                      boolean toInclusive) {
+        SubMap<K,V> newSubMap(K fromKey, boolean fromInclusive,
+                              K toKey, boolean toInclusive) {
+            Comparator<? super K> cmp = m.comparator;
             if (isDescending) { // flip senses
                 K tk = fromKey;
                 fromKey = toKey;
@@ -2838,7 +2917,7 @@
                     fromInclusive = loInclusive;
                 }
                 else {
-                    int c = m.compare(fromKey, lo);
+                    int c = cpr(cmp, fromKey, lo);
                     if (c < 0 || (c == 0 && !loInclusive && fromInclusive))
                         throw new IllegalArgumentException("key out of range");
                 }
@@ -2849,7 +2928,7 @@
                     toInclusive = hiInclusive;
                 }
                 else {
-                    int c = m.compare(toKey, hi);
+                    int c = cpr(cmp, toKey, hi);
                     if (c > 0 || (c == 0 && !hiInclusive && toInclusive))
                         throw new IllegalArgumentException("key out of range");
                 }
@@ -2858,24 +2937,20 @@
                                    toKey, toInclusive, isDescending);
         }
 
-        public SubMap<K,V> subMap(K fromKey,
-                                  boolean fromInclusive,
-                                  K toKey,
-                                  boolean toInclusive) {
+        public SubMap<K,V> subMap(K fromKey, boolean fromInclusive,
+                                  K toKey, boolean toInclusive) {
             if (fromKey == null || toKey == null)
                 throw new NullPointerException();
             return newSubMap(fromKey, fromInclusive, toKey, toInclusive);
         }
 
-        public SubMap<K,V> headMap(K toKey,
-                                   boolean inclusive) {
+        public SubMap<K,V> headMap(K toKey, boolean inclusive) {
             if (toKey == null)
                 throw new NullPointerException();
             return newSubMap(null, false, toKey, inclusive);
         }
 
-        public SubMap<K,V> tailMap(K fromKey,
-                                   boolean inclusive) {
+        public SubMap<K,V> tailMap(K fromKey, boolean inclusive) {
             if (fromKey == null)
                 throw new NullPointerException();
             return newSubMap(fromKey, inclusive, null, false);
@@ -2996,8 +3071,9 @@
 
         /**
          * Variant of main Iter class to traverse through submaps.
+         * Also serves as back-up Spliterator for views
          */
-        abstract class SubMapIter<T> implements Iterator<T> {
+        abstract class SubMapIter<T> implements Iterator<T>, Spliterator<T> {
             /** the last node returned by next() */
             Node<K,V> lastReturned;
             /** the next node to return from next(); */
@@ -3006,16 +3082,19 @@
             V nextValue;
 
             SubMapIter() {
+                Comparator<? super K> cmp = m.comparator;
                 for (;;) {
-                    next = isDescending ? hiNode() : loNode();
+                    next = isDescending ? hiNode(cmp) : loNode(cmp);
                     if (next == null)
                         break;
                     Object x = next.value;
                     if (x != null && x != next) {
-                        if (! inBounds(next.key))
+                        if (! inBounds(next.key, cmp))
                             next = null;
-                        else
-                            nextValue = (V) x;
+                        else {
+                            @SuppressWarnings("unchecked") V vv = (V)x;
+                            nextValue = vv;
+                        }
                         break;
                     }
                 }
@@ -3036,32 +3115,38 @@
             }
 
             private void ascend() {
+                Comparator<? super K> cmp = m.comparator;
                 for (;;) {
                     next = next.next;
                     if (next == null)
                         break;
                     Object x = next.value;
                     if (x != null && x != next) {
-                        if (tooHigh(next.key))
+                        if (tooHigh(next.key, cmp))
                             next = null;
-                        else
-                            nextValue = (V) x;
+                        else {
+                            @SuppressWarnings("unchecked") V vv = (V)x;
+                            nextValue = vv;
+                        }
                         break;
                     }
                 }
             }
 
             private void descend() {
+                Comparator<? super K> cmp = m.comparator;
                 for (;;) {
-                    next = m.findNear(lastReturned.key, LT);
+                    next = m.findNear(lastReturned.key, LT, cmp);
                     if (next == null)
                         break;
                     Object x = next.value;
                     if (x != null && x != next) {
-                        if (tooLow(next.key))
+                        if (tooLow(next.key, cmp))
                             next = null;
-                        else
-                            nextValue = (V) x;
+                        else {
+                            @SuppressWarnings("unchecked") V vv = (V)x;
+                            nextValue = vv;
+                        }
                         break;
                     }
                 }
@@ -3075,6 +3160,26 @@
                 lastReturned = null;
             }
 
+            public Spliterator<T> trySplit() {
+                return null;
+            }
+
+            public boolean tryAdvance(Consumer<? super T> action) {
+                if (hasNext()) {
+                    action.accept(next());
+                    return true;
+                }
+                return false;
+            }
+
+            public void forEachRemaining(Consumer<? super T> action) {
+                while (hasNext())
+                    action.accept(next());
+            }
+
+            public long estimateSize() {
+                return Long.MAX_VALUE;
+            }
         }
 
         final class SubMapValueIterator extends SubMapIter<V> {
@@ -3083,6 +3188,9 @@
                 advance();
                 return v;
             }
+            public int characteristics() {
+                return 0;
+            }
         }
 
         final class SubMapKeyIterator extends SubMapIter<K> {
@@ -3091,6 +3199,13 @@
                 advance();
                 return n.key;
             }
+            public int characteristics() {
+                return Spliterator.DISTINCT | Spliterator.ORDERED |
+                    Spliterator.SORTED;
+            }
+            public final Comparator<? super K> getComparator() {
+                return SubMap.this.comparator();
+            }
         }
 
         final class SubMapEntryIterator extends SubMapIter<Map.Entry<K,V>> {
@@ -3100,18 +3215,351 @@
                 advance();
                 return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
             }
+            public int characteristics() {
+                return Spliterator.DISTINCT;
+            }
+        }
+    }
+
+    // default Map method overrides
+
+    public void forEach(BiConsumer<? super K, ? super V> action) {
+        if (action == null) throw new NullPointerException();
+        V v;
+        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+            if ((v = n.getValidValue()) != null)
+                action.accept(n.key, v);
+        }
+    }
+
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        if (function == null) throw new NullPointerException();
+        V v;
+        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+            while ((v = n.getValidValue()) != null) {
+                V r = function.apply(n.key, v);
+                if (r == null) throw new NullPointerException();
+                if (n.casValue(v, r))
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Base class providing common structure for Spliterators.
+     * (Although not all that much common functionality; as usual for
+     * view classes, details annoyingly vary in key, value, and entry
+     * subclasses in ways that are not worth abstracting out for
+     * internal classes.)
+     *
+     * The basic split strategy is to recursively descend from top
+     * level, row by row, descending to next row when either split
+     * off, or the end of row is encountered. Control of the number of
+     * splits relies on some statistical estimation: The expected
+     * remaining number of elements of a skip list when advancing
+     * either across or down decreases by about 25%. To make this
+     * observation useful, we need to know initial size, which we
+     * don't. But we can just use Integer.MAX_VALUE so that we
+     * don't prematurely zero out while splitting.
+     */
+    abstract static class CSLMSpliterator<K,V> {
+        final Comparator<? super K> comparator;
+        final K fence;     // exclusive upper bound for keys, or null if to end
+        Index<K,V> row;    // the level to split out
+        Node<K,V> current; // current traversal node; initialize at origin
+        int est;           // pseudo-size estimate
+        CSLMSpliterator(Comparator<? super K> comparator, Index<K,V> row,
+                        Node<K,V> origin, K fence, int est) {
+            this.comparator = comparator; this.row = row;
+            this.current = origin; this.fence = fence; this.est = est;
+        }
+
+        public final long estimateSize() { return (long)est; }
+    }
+
+    static final class KeySpliterator<K,V> extends CSLMSpliterator<K,V>
+        implements Spliterator<K> {
+        KeySpliterator(Comparator<? super K> comparator, Index<K,V> row,
+                       Node<K,V> origin, K fence, int est) {
+            super(comparator, row, origin, fence, est);
+        }
+
+        public Spliterator<K> trySplit() {
+            Node<K,V> e; K ek;
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            if ((e = current) != null && (ek = e.key) != null) {
+                for (Index<K,V> q = row; q != null; q = row = q.down) {
+                    Index<K,V> s; Node<K,V> b, n; K sk;
+                    if ((s = q.right) != null && (b = s.node) != null &&
+                        (n = b.next) != null && n.value != null &&
+                        (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
+                        (f == null || cpr(cmp, sk, f) < 0)) {
+                        current = n;
+                        Index<K,V> r = q.down;
+                        row = (s.right != null) ? s : s.down;
+                        est -= est >>> 2;
+                        return new KeySpliterator<K,V>(cmp, r, e, sk, est);
+                    }
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super K> action) {
+            if (action == null) throw new NullPointerException();
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            Node<K,V> e = current;
+            current = null;
+            for (; e != null; e = e.next) {
+                K k; Object v;
+                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
+                    break;
+                if ((v = e.value) != null && v != e)
+                    action.accept(k);
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super K> action) {
+            if (action == null) throw new NullPointerException();
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            Node<K,V> e = current;
+            for (; e != null; e = e.next) {
+                K k; Object v;
+                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
+                    e = null;
+                    break;
+                }
+                if ((v = e.value) != null && v != e) {
+                    current = e.next;
+                    action.accept(k);
+                    return true;
+                }
+            }
+            current = e;
+            return false;
+        }
+
+        public int characteristics() {
+            return Spliterator.DISTINCT | Spliterator.SORTED |
+                Spliterator.ORDERED | Spliterator.CONCURRENT |
+                Spliterator.NONNULL;
+        }
+
+        public final Comparator<? super K> getComparator() {
+            return comparator;
+        }
+    }
+    // factory method for KeySpliterator
+    final KeySpliterator<K,V> keySpliterator() {
+        Comparator<? super K> cmp = comparator;
+        for (;;) { // ensure h corresponds to origin p
+            HeadIndex<K,V> h; Node<K,V> p;
+            Node<K,V> b = (h = head).node;
+            if ((p = b.next) == null || p.value != null)
+                return new KeySpliterator<K,V>(cmp, h, p, null, (p == null) ?
+                                               0 : Integer.MAX_VALUE);
+            p.helpDelete(b, p.next);
+        }
+    }
+
+    static final class ValueSpliterator<K,V> extends CSLMSpliterator<K,V>
+        implements Spliterator<V> {
+        ValueSpliterator(Comparator<? super K> comparator, Index<K,V> row,
+                       Node<K,V> origin, K fence, int est) {
+            super(comparator, row, origin, fence, est);
+        }
+
+        public Spliterator<V> trySplit() {
+            Node<K,V> e; K ek;
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            if ((e = current) != null && (ek = e.key) != null) {
+                for (Index<K,V> q = row; q != null; q = row = q.down) {
+                    Index<K,V> s; Node<K,V> b, n; K sk;
+                    if ((s = q.right) != null && (b = s.node) != null &&
+                        (n = b.next) != null && n.value != null &&
+                        (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
+                        (f == null || cpr(cmp, sk, f) < 0)) {
+                        current = n;
+                        Index<K,V> r = q.down;
+                        row = (s.right != null) ? s : s.down;
+                        est -= est >>> 2;
+                        return new ValueSpliterator<K,V>(cmp, r, e, sk, est);
+                    }
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super V> action) {
+            if (action == null) throw new NullPointerException();
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            Node<K,V> e = current;
+            current = null;
+            for (; e != null; e = e.next) {
+                K k; Object v;
+                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
+                    break;
+                if ((v = e.value) != null && v != e) {
+                    @SuppressWarnings("unchecked") V vv = (V)v;
+                    action.accept(vv);
+                }
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super V> action) {
+            if (action == null) throw new NullPointerException();
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            Node<K,V> e = current;
+            for (; e != null; e = e.next) {
+                K k; Object v;
+                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
+                    e = null;
+                    break;
+                }
+                if ((v = e.value) != null && v != e) {
+                    current = e.next;
+                    @SuppressWarnings("unchecked") V vv = (V)v;
+                    action.accept(vv);
+                    return true;
+                }
+            }
+            current = e;
+            return false;
+        }
+
+        public int characteristics() {
+            return Spliterator.CONCURRENT | Spliterator.NONNULL;
+        }
+    }
+
+    // Almost the same as keySpliterator()
+    final ValueSpliterator<K,V> valueSpliterator() {
+        Comparator<? super K> cmp = comparator;
+        for (;;) {
+            HeadIndex<K,V> h; Node<K,V> p;
+            Node<K,V> b = (h = head).node;
+            if ((p = b.next) == null || p.value != null)
+                return new ValueSpliterator<K,V>(cmp, h, p, null, (p == null) ?
+                                                 0 : Integer.MAX_VALUE);
+            p.helpDelete(b, p.next);
+        }
+    }
+
+    static final class EntrySpliterator<K,V> extends CSLMSpliterator<K,V>
+        implements Spliterator<Map.Entry<K,V>> {
+        EntrySpliterator(Comparator<? super K> comparator, Index<K,V> row,
+                         Node<K,V> origin, K fence, int est) {
+            super(comparator, row, origin, fence, est);
+        }
+
+        public Spliterator<Map.Entry<K,V>> trySplit() {
+            Node<K,V> e; K ek;
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            if ((e = current) != null && (ek = e.key) != null) {
+                for (Index<K,V> q = row; q != null; q = row = q.down) {
+                    Index<K,V> s; Node<K,V> b, n; K sk;
+                    if ((s = q.right) != null && (b = s.node) != null &&
+                        (n = b.next) != null && n.value != null &&
+                        (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
+                        (f == null || cpr(cmp, sk, f) < 0)) {
+                        current = n;
+                        Index<K,V> r = q.down;
+                        row = (s.right != null) ? s : s.down;
+                        est -= est >>> 2;
+                        return new EntrySpliterator<K,V>(cmp, r, e, sk, est);
+                    }
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
+            if (action == null) throw new NullPointerException();
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            Node<K,V> e = current;
+            current = null;
+            for (; e != null; e = e.next) {
+                K k; Object v;
+                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
+                    break;
+                if ((v = e.value) != null && v != e) {
+                    @SuppressWarnings("unchecked") V vv = (V)v;
+                    action.accept
+                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, vv));
+                }
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
+            if (action == null) throw new NullPointerException();
+            Comparator<? super K> cmp = comparator;
+            K f = fence;
+            Node<K,V> e = current;
+            for (; e != null; e = e.next) {
+                K k; Object v;
+                if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
+                    e = null;
+                    break;
+                }
+                if ((v = e.value) != null && v != e) {
+                    current = e.next;
+                    @SuppressWarnings("unchecked") V vv = (V)v;
+                    action.accept
+                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, vv));
+                    return true;
+                }
+            }
+            current = e;
+            return false;
+        }
+
+        public int characteristics() {
+            return Spliterator.DISTINCT | Spliterator.SORTED |
+                Spliterator.ORDERED | Spliterator.CONCURRENT |
+                Spliterator.NONNULL;
+        }
+
+        public final Comparator<Map.Entry<K,V>> getComparator() {
+            return comparator == null ? null :
+                Map.Entry.comparingByKey(comparator);
+        }
+    }
+
+    // Almost the same as keySpliterator()
+    final EntrySpliterator<K,V> entrySpliterator() {
+        Comparator<? super K> cmp = comparator;
+        for (;;) { // almost same as key version
+            HeadIndex<K,V> h; Node<K,V> p;
+            Node<K,V> b = (h = head).node;
+            if ((p = b.next) == null || p.value != null)
+                return new EntrySpliterator<K,V>(cmp, h, p, null, (p == null) ?
+                                                 0 : Integer.MAX_VALUE);
+            p.helpDelete(b, p.next);
         }
     }
 
     // Unsafe mechanics
     private static final sun.misc.Unsafe UNSAFE;
     private static final long headOffset;
+    private static final long SECONDARY;
     static {
         try {
             UNSAFE = sun.misc.Unsafe.getUnsafe();
             Class<?> k = ConcurrentSkipListMap.class;
             headOffset = UNSAFE.objectFieldOffset
                 (k.getDeclaredField("head"));
+            Class<?> tk = Thread.class;
+            SECONDARY = UNSAFE.objectFieldOffset
+                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
+
         } catch (Exception e) {
             throw new Error(e);
         }
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Wed Jul 03 11:58:09 2013 +0200
@@ -34,7 +34,17 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.Spliterator;
 
 /**
  * A scalable concurrent {@link NavigableSet} implementation based on
@@ -44,33 +54,33 @@
  * on which constructor is used.
  *
  * <p>This implementation provides expected average <i>log(n)</i> time
- * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
+ * cost for the {@code contains}, {@code add}, and {@code remove}
  * operations and their variants.  Insertion, removal, and access
  * operations safely execute concurrently by multiple threads.
  * Iterators are <i>weakly consistent</i>, returning elements
  * reflecting the state of the set 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 ordered views and their iterators are
- * faster than descending ones.
+ * java.util.ConcurrentModificationException}, and may proceed
+ * concurrently with other operations.  Ascending ordered views and
+ * their iterators are faster than descending ones.
  *
- * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * <p>Beware that, unlike in most collections, the {@code size}
  * method is <em>not</em> a constant-time operation. Because of the
  * asynchronous nature of these sets, determining the current number
  * of elements requires a traversal of the elements, and so may report
  * inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations <tt>addAll</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt>, <tt>containsAll</tt>,
- * <tt>equals</tt>, and <tt>toArray</tt> are <em>not</em> guaranteed
+ * Additionally, the bulk operations {@code addAll},
+ * {@code removeAll}, {@code retainAll}, {@code containsAll},
+ * {@code equals}, and {@code toArray} are <em>not</em> guaranteed
  * to be performed atomically. For example, an iterator operating
- * concurrently with an <tt>addAll</tt> operation might view only some
+ * concurrently with an {@code addAll} operation might view only some
  * of the added elements.
  *
  * <p>This class and its iterators implement all of the
  * <em>optional</em> methods of the {@link Set} and {@link Iterator}
  * interfaces. Like most other concurrent collection implementations,
- * this class does not permit the use of <tt>null</tt> elements,
- * because <tt>null</tt> arguments and return values cannot be reliably
+ * this class does not permit the use of {@code null} elements,
+ * because {@code null} arguments and return values cannot be reliably
  * distinguished from the absence of elements.
  *
  * <p>This class is a member of the
@@ -90,7 +100,7 @@
     /**
      * The underlying map. Uses Boolean.TRUE as value for each
      * element.  This field is declared final for the sake of thread
-     * safety, which entails some ugliness in clone()
+     * safety, which entails some ugliness in clone().
      */
     private final ConcurrentNavigableMap<E,Object> m;
 
@@ -107,7 +117,7 @@
      * the specified comparator.
      *
      * @param comparator the comparator that will be used to order this set.
-     *        If <tt>null</tt>, the {@linkplain Comparable natural
+     *        If {@code null}, the {@linkplain Comparable natural
      *        ordering} of the elements will be used.
      */
     public ConcurrentSkipListSet(Comparator<? super E> comparator) {
@@ -120,7 +130,7 @@
      * {@linkplain Comparable natural ordering}.
      *
      * @param c The elements that will comprise the new set
-     * @throws ClassCastException if the elements in <tt>c</tt> are
+     * @throws ClassCastException if the elements in {@code c} are
      *         not {@link Comparable}, or are not mutually comparable
      * @throws NullPointerException if the specified collection or any
      *         of its elements are null
@@ -151,7 +161,7 @@
     }
 
     /**
-     * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
+     * Returns a shallow copy of this {@code ConcurrentSkipListSet}
      * instance. (The elements themselves are not cloned.)
      *
      * @return a shallow copy of this set
@@ -172,8 +182,8 @@
 
     /**
      * Returns the number of elements in this set.  If this set
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
-     * returns <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, it
+     * returns {@code Integer.MAX_VALUE}.
      *
      * <p>Beware that, unlike in most collections, this method is
      * <em>NOT</em> a constant-time operation. Because of the
@@ -191,20 +201,20 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains no elements.
-     * @return <tt>true</tt> if this set contains no elements
+     * Returns {@code true} if this set contains no elements.
+     * @return {@code true} if this set contains no elements
      */
     public boolean isEmpty() {
         return m.isEmpty();
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this set
-     * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this set contains the specified element.
+     * More formally, returns {@code true} if and only if this set
+     * contains an element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this set
-     * @return <tt>true</tt> if this set contains the specified element
+     * @return {@code true} if this set contains the specified element
      * @throws ClassCastException if the specified element cannot be
      *         compared with the elements currently in this set
      * @throws NullPointerException if the specified element is null
@@ -215,15 +225,15 @@
 
     /**
      * Adds the specified element to this set if it is not already present.
-     * More formally, adds the specified element <tt>e</tt> to this set if
-     * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
+     * More formally, adds the specified element {@code e} to this set if
+     * the set contains no element {@code e2} such that {@code e.equals(e2)}.
      * If this set already contains the element, the call leaves the set
-     * unchanged and returns <tt>false</tt>.
+     * unchanged and returns {@code false}.
      *
      * @param e element to be added to this set
-     * @return <tt>true</tt> if this set did not already contain the
+     * @return {@code true} if this set did not already contain the
      *         specified element
-     * @throws ClassCastException if <tt>e</tt> cannot be compared
+     * @throws ClassCastException if {@code e} cannot be compared
      *         with the elements currently in this set
      * @throws NullPointerException if the specified element is null
      */
@@ -233,15 +243,15 @@
 
     /**
      * Removes the specified element from this set if it is present.
-     * More formally, removes an element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt>, if this set contains such an element.
-     * Returns <tt>true</tt> if this set contained the element (or
+     * More formally, removes an element {@code e} such that
+     * {@code o.equals(e)}, if this set contains such an element.
+     * Returns {@code true} if this set contained the element (or
      * equivalently, if this set changed as a result of the call).
      * (This set will not contain the element once the call returns.)
      *
      * @param o object to be removed from this set, if present
-     * @return <tt>true</tt> if this set contained the specified element
-     * @throws ClassCastException if <tt>o</tt> cannot be compared
+     * @return {@code true} if this set contained the specified element
+     * @throws ClassCastException if {@code o} cannot be compared
      *         with the elements currently in this set
      * @throws NullPointerException if the specified element is null
      */
@@ -279,7 +289,7 @@
 
     /**
      * Compares the specified object with this set for equality.  Returns
-     * <tt>true</tt> if the specified object is also a set, the two sets
+     * {@code true} if the specified object is also a set, the two sets
      * have the same size, and every member of the specified set is
      * contained in this set (or equivalently, every member of this set is
      * contained in the specified set).  This definition ensures that the
@@ -287,7 +297,7 @@
      * set interface.
      *
      * @param o the object to be compared for equality with this set
-     * @return <tt>true</tt> if the specified object is equal to this set
+     * @return {@code true} if the specified object is equal to this set
      */
     public boolean equals(Object o) {
         // Override AbstractSet version to avoid calling size()
@@ -312,7 +322,7 @@
      * value is the <i>asymmetric set difference</i> of the two sets.
      *
      * @param  c collection containing elements to be removed from this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the types of one or more elements in this
      *         set are incompatible with the specified collection
      * @throws NullPointerException if the specified collection or any
@@ -380,14 +390,14 @@
     }
 
     /**
-     * @throws NoSuchElementException {@inheritDoc}
+     * @throws java.util.NoSuchElementException {@inheritDoc}
      */
     public E first() {
         return m.firstKey();
     }
 
     /**
-     * @throws NoSuchElementException {@inheritDoc}
+     * @throws java.util.NoSuchElementException {@inheritDoc}
      */
     public E last() {
         return m.lastKey();
@@ -460,7 +470,7 @@
      * reflected in the descending set, and vice-versa.
      *
      * <p>The returned set has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code s.descendingSet().descendingSet()} returns a
      * view of {@code s} essentially equivalent to {@code s}.
      *
@@ -470,6 +480,14 @@
         return new ConcurrentSkipListSet<E>(m.descendingMap());
     }
 
+    @SuppressWarnings("unchecked")
+    public Spliterator<E> spliterator() {
+        if (m instanceof ConcurrentSkipListMap)
+            return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
+        else
+            return (Spliterator<E>)((ConcurrentSkipListMap.SubMap<E,?>)m).keyIterator();
+    }
+
     // Support for resetting map in clone
     private void setMap(ConcurrentNavigableMap<E,Object> map) {
         UNSAFE.putObjectVolatile(this, mapOffset, map);
--- a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed Jul 03 11:58:09 2013 +0200
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +33,19 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.RandomAccess;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -42,10 +53,10 @@
 
 /**
  * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
- * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by
+ * operations ({@code add}, {@code set}, and so on) are implemented by
  * making a fresh copy of the underlying array.
  *
- * <p> This is ordinarily too costly, but may be <em>more</em> efficient
+ * <p>This is ordinarily too costly, but may be <em>more</em> efficient
  * than alternatives when traversal operations vastly outnumber
  * mutations, and is useful when you cannot or don't want to
  * synchronize traversals, yet need to preclude interference among
@@ -53,14 +64,14 @@
  * reference to the state of the array at the point that the iterator
  * was created. This array never changes during the lifetime of the
  * iterator, so interference is impossible and the iterator is
- * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
+ * guaranteed not to throw {@code ConcurrentModificationException}.
  * The iterator will not reflect additions, removals, or changes to
  * the list since the iterator was created.  Element-changing
- * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and
- * <tt>add</tt>) are not supported. These methods throw
- * <tt>UnsupportedOperationException</tt>.
+ * operations on iterators themselves ({@code remove}, {@code set}, and
+ * {@code add}) are not supported. These methods throw
+ * {@code UnsupportedOperationException}.
  *
- * <p>All elements are permitted, including <tt>null</tt>.
+ * <p>All elements are permitted, including {@code null}.
  *
  * <p>Memory consistency effects: As with other concurrent
  * collections, actions in a thread prior to placing an object into a
@@ -82,10 +93,10 @@
     private static final long serialVersionUID = 8673264195747942595L;
 
     /** The lock protecting all mutators */
-    transient final ReentrantLock lock = new ReentrantLock();
+    final transient ReentrantLock lock = new ReentrantLock();
 
     /** The array, accessed only via getArray/setArray. */
-    private volatile transient Object[] array;
+    private transient volatile Object[] array;
 
     /**
      * Gets the array.  Non-private so as to also be accessible
@@ -118,10 +129,15 @@
      * @throws NullPointerException if the specified collection is null
      */
     public CopyOnWriteArrayList(Collection<? extends E> c) {
-        Object[] elements = c.toArray();
-        // c.toArray might (incorrectly) not return Object[] (see 6260652)
-        if (elements.getClass() != Object[].class)
-            elements = Arrays.copyOf(elements, elements.length, Object[].class);
+        Object[] elements;
+        if (c.getClass() == CopyOnWriteArrayList.class)
+            elements = ((CopyOnWriteArrayList<?>)c).getArray();
+        else {
+            elements = c.toArray();
+            // c.toArray might (incorrectly) not return Object[] (see 6260652)
+            if (elements.getClass() != Object[].class)
+                elements = Arrays.copyOf(elements, elements.length, Object[].class);
+        }
         setArray(elements);
     }
 
@@ -146,9 +162,9 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this list contains no elements.
+     * Returns {@code true} if this list contains no elements.
      *
-     * @return <tt>true</tt> if this list contains no elements
+     * @return {@code true} if this list contains no elements
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -158,7 +174,7 @@
      * Tests for equality, coping with nulls.
      */
     private static boolean eq(Object o1, Object o2) {
-        return (o1 == null ? o2 == null : o1.equals(o2));
+        return (o1 == null) ? o2 == null : o1.equals(o2);
     }
 
     /**
@@ -205,13 +221,13 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this list contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this list contains
-     * at least one element <tt>e</tt> such that
+     * Returns {@code true} if this list contains the specified element.
+     * More formally, returns {@code true} if and only if this list contains
+     * at least one element {@code e} such that
      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
      *
      * @param o element whose presence in this list is to be tested
-     * @return <tt>true</tt> if this list contains the specified element
+     * @return {@code true} if this list contains the specified element
      */
     public boolean contains(Object o) {
         Object[] elements = getArray();
@@ -228,17 +244,17 @@
 
     /**
      * Returns the index of the first occurrence of the specified element in
-     * this list, searching forwards from <tt>index</tt>, or returns -1 if
+     * this list, searching forwards from {@code index}, or returns -1 if
      * the element is not found.
-     * More formally, returns the lowest index <tt>i</tt> such that
+     * More formally, returns the lowest index {@code i} such that
      * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
      * or -1 if there is no such index.
      *
      * @param e element to search for
      * @param index index to start searching from
      * @return the index of the first occurrence of the element in
-     *         this list at position <tt>index</tt> or later in the list;
-     *         <tt>-1</tt> if the element is not found.
+     *         this list at position {@code index} or later in the list;
+     *         {@code -1} if the element is not found.
      * @throws IndexOutOfBoundsException if the specified index is negative
      */
     public int indexOf(E e, int index) {
@@ -256,16 +272,16 @@
 
     /**
      * Returns the index of the last occurrence of the specified element in
-     * this list, searching backwards from <tt>index</tt>, or returns -1 if
+     * this list, searching backwards from {@code index}, or returns -1 if
      * the element is not found.
-     * More formally, returns the highest index <tt>i</tt> such that
+     * More formally, returns the highest index {@code i} such that
      * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
      * or -1 if there is no such index.
      *
      * @param e element to search for
      * @param index index to start searching backwards from
      * @return the index of the last occurrence of the element at position
-     *         less than or equal to <tt>index</tt> in this list;
+     *         less than or equal to {@code index} in this list;
      *         -1 if the element is not found.
      * @throws IndexOutOfBoundsException if the specified index is greater
      *         than or equal to the current size of this list
@@ -323,7 +339,7 @@
      * <p>If this list fits in the specified array with room to spare
      * (i.e., the array has more elements than this list), the element in
      * the array immediately following the end of the list is set to
-     * <tt>null</tt>.  (This is useful in determining the length of this
+     * {@code null}.  (This is useful in determining the length of this
      * list <i>only</i> if the caller knows that this list does not contain
      * any null elements.)
      *
@@ -332,14 +348,14 @@
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a list known to contain only strings.
+     * <p>Suppose {@code x} is a list known to contain only strings.
      * The following code can be used to dump the list into a newly
-     * allocated array of <tt>String</tt>:
+     * allocated array of {@code String}:
      *
      *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the list are to
      *          be stored, if it is big enough; otherwise, a new array of the
@@ -412,7 +428,7 @@
      * Appends the specified element to the end of this list.
      *
      * @param e element to be appended to this list
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
         final ReentrantLock lock = this.lock;
@@ -496,45 +512,54 @@
      * Removes the first occurrence of the specified element from this list,
      * if it is present.  If this list does not contain the element, it is
      * unchanged.  More formally, removes the element with the lowest index
-     * <tt>i</tt> such that
+     * {@code i} such that
      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
-     * (if such an element exists).  Returns <tt>true</tt> if this list
+     * (if such an element exists).  Returns {@code true} if this list
      * contained the specified element (or equivalently, if this list
      * changed as a result of the call).
      *
      * @param o element to be removed from this list, if present
-     * @return <tt>true</tt> if this list contained the specified element
+     * @return {@code true} if this list contained the specified element
      */
     public boolean remove(Object o) {
+        Object[] snapshot = getArray();
+        int index = indexOf(o, snapshot, 0, snapshot.length);
+        return (index < 0) ? false : remove(o, snapshot, index);
+    }
+
+    /**
+     * A version of remove(Object) using the strong hint that given
+     * recent snapshot contains o at the given index.
+     */
+    private boolean remove(Object o, Object[] snapshot, int index) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // Copy while searching for element to remove
-                // This wins in the normal case of element being present
-                int newlen = len - 1;
-                Object[] newElements = new Object[newlen];
-
-                for (int i = 0; i < newlen; ++i) {
-                    if (eq(o, elements[i])) {
-                        // found one;  copy remaining and exit
-                        for (int k = i + 1; k < len; ++k)
-                            newElements[k-1] = elements[k];
-                        setArray(newElements);
-                        return true;
-                    } else
-                        newElements[i] = elements[i];
+            Object[] current = getArray();
+            int len = current.length;
+            if (snapshot != current) findIndex: {
+                int prefix = Math.min(index, len);
+                for (int i = 0; i < prefix; i++) {
+                    if (current[i] != snapshot[i] && eq(o, current[i])) {
+                        index = i;
+                        break findIndex;
+                    }
                 }
-
-                // special handling for last cell
-                if (eq(o, elements[newlen])) {
-                    setArray(newElements);
-                    return true;
-                }
+                if (index >= len)
+                    return false;
+                if (current[index] == o)
+                    break findIndex;
+                index = indexOf(o, current, index, len);
+                if (index < 0)
+                    return false;
             }
-            return false;
+            Object[] newElements = new Object[len - 1];
+            System.arraycopy(current, 0, newElements, 0, index);
+            System.arraycopy(current, index + 1,
+                             newElements, index,
+                             len - index - 1);
+            setArray(newElements);
+            return true;
         } finally {
             lock.unlock();
         }
@@ -542,10 +567,10 @@
 
     /**
      * Removes from this list all of the elements whose index is between
-     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
+     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
      * Shifts any succeeding elements to the left (reduces their index).
-     * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
-     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
+     * This call shortens the list by {@code (toIndex - fromIndex)} elements.
+     * (If {@code toIndex==fromIndex}, this operation has no effect.)
      *
      * @param fromIndex index of first element to be removed
      * @param toIndex index after last element to be removed
@@ -581,23 +606,34 @@
      * Appends the element, if not present.
      *
      * @param e element to be added to this list, if absent
-     * @return <tt>true</tt> if the element was added
+     * @return {@code true} if the element was added
      */
     public boolean addIfAbsent(E e) {
+        Object[] snapshot = getArray();
+        return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
+            addIfAbsent(e, snapshot);
+    }
+
+    /**
+     * A version of addIfAbsent using the strong hint that given
+     * recent snapshot does not contain e.
+     */
+    private boolean addIfAbsent(E e, Object[] snapshot) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            // Copy while checking if already present.
-            // This wins in the most common case where it is not present
-            Object[] elements = getArray();
-            int len = elements.length;
-            Object[] newElements = new Object[len + 1];
-            for (int i = 0; i < len; ++i) {
-                if (eq(e, elements[i]))
-                    return false; // exit, throwing away copy
-                else
-                    newElements[i] = elements[i];
+            Object[] current = getArray();
+            int len = current.length;
+            if (snapshot != current) {
+                // Optimize for lost race to another addXXX operation
+                int common = Math.min(snapshot.length, len);
+                for (int i = 0; i < common; i++)
+                    if (current[i] != snapshot[i] && eq(e, current[i]))
+                        return false;
+                if (indexOf(e, current, common, len) >= 0)
+                        return false;
             }
+            Object[] newElements = Arrays.copyOf(current, len + 1);
             newElements[len] = e;
             setArray(newElements);
             return true;
@@ -607,11 +643,11 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this list contains all of the elements of the
+     * Returns {@code true} if this list contains all of the elements of the
      * specified collection.
      *
      * @param c collection to be checked for containment in this list
-     * @return <tt>true</tt> if this list contains all of the elements of the
+     * @return {@code true} if this list contains all of the elements of the
      *         specified collection
      * @throws NullPointerException if the specified collection is null
      * @see #contains(Object)
@@ -632,7 +668,7 @@
      * in this class because of the need for an internal temporary array.
      *
      * @param c collection containing elements to be removed from this list
-     * @return <tt>true</tt> if this list changed as a result of the call
+     * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -675,7 +711,7 @@
      * its elements that are not contained in the specified collection.
      *
      * @param c collection containing elements to be retained in this list
-     * @return <tt>true</tt> if this list changed as a result of the call
+     * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -727,22 +763,22 @@
         Object[] cs = c.toArray();
         if (cs.length == 0)
             return 0;
-        Object[] uniq = new Object[cs.length];
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             Object[] elements = getArray();
             int len = elements.length;
             int added = 0;
-            for (int i = 0; i < cs.length; ++i) { // scan for duplicates
+            // uniquify and compact elements in cs
+            for (int i = 0; i < cs.length; ++i) {
                 Object e = cs[i];
                 if (indexOf(e, elements, 0, len) < 0 &&
-                    indexOf(e, uniq, 0, added) < 0)
-                    uniq[added++] = e;
+                    indexOf(e, cs, 0, added) < 0)
+                    cs[added++] = e;
             }
             if (added > 0) {
                 Object[] newElements = Arrays.copyOf(elements, len + added);
-                System.arraycopy(uniq, 0, newElements, len, added);
+                System.arraycopy(cs, 0, newElements, len, added);
                 setArray(newElements);
             }
             return added;
@@ -771,12 +807,13 @@
      * collection's iterator.
      *
      * @param c collection containing elements to be added to this list
-     * @return <tt>true</tt> if this list changed as a result of the call
+     * @return {@code true} if this list changed as a result of the call
      * @throws NullPointerException if the specified collection is null
      * @see #add(Object)
      */
     public boolean addAll(Collection<? extends E> c) {
-        Object[] cs = c.toArray();
+        Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
+            ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
         if (cs.length == 0)
             return false;
         final ReentrantLock lock = this.lock;
@@ -784,9 +821,13 @@
         try {
             Object[] elements = getArray();
             int len = elements.length;
-            Object[] newElements = Arrays.copyOf(elements, len + cs.length);
-            System.arraycopy(cs, 0, newElements, len, cs.length);
-            setArray(newElements);
+            if (len == 0 && cs.getClass() == Object[].class)
+                setArray(cs);
+            else {
+                Object[] newElements = Arrays.copyOf(elements, len + cs.length);
+                System.arraycopy(cs, 0, newElements, len, cs.length);
+                setArray(newElements);
+            }
             return true;
         } finally {
             lock.unlock();
@@ -804,7 +845,7 @@
      * @param index index at which to insert the first element
      *        from the specified collection
      * @param c collection containing elements to be added to this list
-     * @return <tt>true</tt> if this list changed as a result of the call
+     * @return {@code true} if this list changed as a result of the call
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @throws NullPointerException if the specified collection is null
      * @see #add(int,Object)
@@ -840,6 +881,74 @@
         }
     }
 
+    public void forEach(Consumer<? super E> action) {
+        if (action == null) throw new NullPointerException();
+        Object[] elements = getArray();
+        int len = elements.length;
+        for (int i = 0; i < len; ++i) {
+            @SuppressWarnings("unchecked") E e = (E) elements[i];
+            action.accept(e);
+        }
+    }
+
+    public boolean removeIf(Predicate<? super E> filter) {
+        if (filter == null) throw new NullPointerException();
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (len != 0) {
+                int newlen = 0;
+                Object[] temp = new Object[len];
+                for (int i = 0; i < len; ++i) {
+                    @SuppressWarnings("unchecked") E e = (E) elements[i];
+                    if (!filter.test(e))
+                        temp[newlen++] = e;
+                }
+                if (newlen != len) {
+                    setArray(Arrays.copyOf(temp, newlen));
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void replaceAll(UnaryOperator<E> operator) {
+        if (operator == null) throw new NullPointerException();
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            Object[] newElements = Arrays.copyOf(elements, len);
+            for (int i = 0; i < len; ++i) {
+                @SuppressWarnings("unchecked") E e = (E) elements[i];
+                newElements[i] = operator.apply(e);
+            }
+            setArray(newElements);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public void sort(Comparator<? super E> c) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            Object[] newElements = Arrays.copyOf(elements, elements.length);
+            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
+            Arrays.sort(es, c);
+            setArray(newElements);
+        } finally {
+            lock.unlock();
+        }
+    }
+
     /**
      * Saves this list to a stream (that is, serializes it).
      *
@@ -886,8 +995,8 @@
      * Returns a string representation of this list.  The string
      * representation consists of the string representations of the list's
      * elements in the order they are returned by its iterator, enclosed in
-     * square brackets (<tt>"[]"</tt>).  Adjacent elements are separated by
-     * the characters <tt>", "</tt> (comma and space).  Elements are
+     * square brackets ({@code "[]"}).  Adjacent elements are separated by
+     * the characters {@code ", "} (comma and space).  Elements are
      * converted to strings as by {@link String#valueOf(Object)}.
      *
      * @return a string representation of this list
@@ -953,7 +1062,7 @@
      * <p>The returned iterator provides a snapshot of the state of the list
      * when the iterator was constructed. No synchronization is needed while
      * traversing the iterator. The iterator does <em>NOT</em> support the
-     * <tt>remove</tt> method.
+     * {@code remove} method.
      *
      * @return an iterator over the elements in this list in proper sequence
      */
@@ -967,7 +1076,7 @@
      * <p>The returned iterator provides a snapshot of the state of the list
      * when the iterator was constructed. No synchronization is needed while
      * traversing the iterator. The iterator does <em>NOT</em> support the
-     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
+     * {@code remove}, {@code set} or {@code add} methods.
      */
     public ListIterator<E> listIterator() {
         return new COWIterator<E>(getArray(), 0);
@@ -979,7 +1088,7 @@
      * <p>The returned iterator provides a snapshot of the state of the list
      * when the iterator was constructed. No synchronization is needed while
      * traversing the iterator. The iterator does <em>NOT</em> support the
-     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
+     * {@code remove}, {@code set} or {@code add} methods.
      *
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
@@ -992,7 +1101,12 @@
         return new COWIterator<E>(elements, index);
     }
 
-    private static class COWIterator<E> implements ListIterator<E> {
+    public Spliterator<E> spliterator() {
+        return Spliterators.spliterator
+            (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
+    }
+
+    static final class COWIterator<E> implements ListIterator<E> {
         /** Snapshot of the array */
         private final Object[] snapshot;
         /** Index of element to be returned by subsequent call to next.  */
@@ -1035,7 +1149,7 @@
 
         /**
          * Not supported. Always throws UnsupportedOperationException.
-         * @throws UnsupportedOperationException always; <tt>remove</tt>
+         * @throws UnsupportedOperationException always; {@code remove}
          *         is not supported by this iterator.
          */
         public void remove() {
@@ -1044,7 +1158,7 @@
 
         /**
          * Not supported. Always throws UnsupportedOperationException.
-         * @throws UnsupportedOperationException always; <tt>set</tt>
+         * @throws UnsupportedOperationException always; {@code set}
          *         is not supported by this iterator.
          */
         public void set(E e) {
@@ -1053,7 +1167,7 @@
 
         /**
          * Not supported. Always throws UnsupportedOperationException.
-         * @throws UnsupportedOperationException always; <tt>add</tt>
+         * @throws UnsupportedOperationException always; {@code add}
          *         is not supported by this iterator.
          */
         public void add(E e) {
@@ -1061,12 +1175,13 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
-            final int size = snapshot.length;
-            for (int i=cursor; i < size; i++) {
-                action.accept((E) snapshot[i]);
+            Object[] elements = snapshot;
+            final int size = elements.length;
+            for (int i = cursor; i < size; i++) {
+                @SuppressWarnings("unchecked") E e = (E) elements[i];
+                action.accept(e);
             }
             cursor = size;
         }
@@ -1074,7 +1189,7 @@
 
     /**
      * Returns a view of the portion of this list between
-     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
+     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
      * The returned list is backed by this list, so changes in the
      * returned list are reflected in this list.
      *
@@ -1274,55 +1389,196 @@
             }
         }
 
-        @Override
         public void forEach(Consumer<? super E> action) {
-            @SuppressWarnings("unchecked")
-            final E[] elements = (E[]) l.getArray();
-            checkForComodification();
-            l.forEach(action, elements, offset, offset + size);
+            if (action == null) throw new NullPointerException();
+            int lo = offset;
+            int hi = offset + size;
+            Object[] a = expectedArray;
+            if (l.getArray() != a)
+                throw new ConcurrentModificationException();
+            if (lo < 0 || hi > a.length)
+                throw new IndexOutOfBoundsException();
+            for (int i = lo; i < hi; ++i) {
+                @SuppressWarnings("unchecked") E e = (E) a[i];
+                action.accept(e);
+            }
         }
 
-        @Override
+        public void replaceAll(UnaryOperator<E> operator) {
+            if (operator == null) throw new NullPointerException();
+            final ReentrantLock lock = l.lock;
+            lock.lock();
+            try {
+                int lo = offset;
+                int hi = offset + size;
+                Object[] elements = expectedArray;
+                if (l.getArray() != elements)
+                    throw new ConcurrentModificationException();
+                int len = elements.length;
+                if (lo < 0 || hi > len)
+                    throw new IndexOutOfBoundsException();
+                Object[] newElements = Arrays.copyOf(elements, len);
+                for (int i = lo; i < hi; ++i) {
+                    @SuppressWarnings("unchecked") E e = (E) elements[i];
+                    newElements[i] = operator.apply(e);
+                }
+                l.setArray(expectedArray = newElements);
+            } finally {
+                lock.unlock();
+            }
+        }
+
         public void sort(Comparator<? super E> c) {
             final ReentrantLock lock = l.lock;
             lock.lock();
             try {
-                checkForComodification();
-                l.sort(c, offset, offset + size);
-                expectedArray = l.getArray();
+                int lo = offset;
+                int hi = offset + size;
+                Object[] elements = expectedArray;
+                if (l.getArray() != elements)
+                    throw new ConcurrentModificationException();
+                int len = elements.length;
+                if (lo < 0 || hi > len)
+                    throw new IndexOutOfBoundsException();
+                Object[] newElements = Arrays.copyOf(elements, len);
+                @SuppressWarnings("unchecked") E[] es = (E[])newElements;
+                Arrays.sort(es, lo, hi, c);
+                l.setArray(expectedArray = newElements);
             } finally {
                 lock.unlock();
             }
         }
 
-        @Override
-        public boolean removeIf(Predicate<? super E> filter) {
-            Objects.requireNonNull(filter);
+        public boolean removeAll(Collection<?> c) {
+            if (c == null) throw new NullPointerException();
+            boolean removed = false;
+            final ReentrantLock lock = l.lock;
+            lock.lock();
+            try {
+                int n = size;
+                if (n > 0) {
+                    int lo = offset;
+                    int hi = offset + n;
+                    Object[] elements = expectedArray;
+                    if (l.getArray() != elements)
+                        throw new ConcurrentModificationException();
+                    int len = elements.length;
+                    if (lo < 0 || hi > len)
+                        throw new IndexOutOfBoundsException();
+                    int newSize = 0;
+                    Object[] temp = new Object[n];
+                    for (int i = lo; i < hi; ++i) {
+                        Object element = elements[i];
+                        if (!c.contains(element))
+                            temp[newSize++] = element;
+                    }
+                    if (newSize != n) {
+                        Object[] newElements = new Object[len - n + newSize];
+                        System.arraycopy(elements, 0, newElements, 0, lo);
+                        System.arraycopy(temp, 0, newElements, lo, newSize);
+                        System.arraycopy(elements, hi, newElements,
+                                         lo + newSize, len - hi);
+                        size = newSize;
+                        removed = true;
+                        l.setArray(expectedArray = newElements);
+                    }
+                }
+            } finally {
+                lock.unlock();
+            }
+            return removed;
+        }
+
+        public boolean retainAll(Collection<?> c) {
+            if (c == null) throw new NullPointerException();
+            boolean removed = false;
             final ReentrantLock lock = l.lock;
             lock.lock();
             try {
-                checkForComodification();
-                final int removeCount =
-                        l.removeIf(filter, offset, offset + size);
-                expectedArray = l.getArray();
-                size -= removeCount;
-                return removeCount > 0;
+                int n = size;
+                if (n > 0) {
+                    int lo = offset;
+                    int hi = offset + n;
+                    Object[] elements = expectedArray;
+                    if (l.getArray() != elements)
+                        throw new ConcurrentModificationException();
+                    int len = elements.length;
+                    if (lo < 0 || hi > len)
+                        throw new IndexOutOfBoundsException();
+                    int newSize = 0;
+                    Object[] temp = new Object[n];
+                    for (int i = lo; i < hi; ++i) {
+                        Object element = elements[i];
+                        if (c.contains(element))
+                            temp[newSize++] = element;
+                    }
+                    if (newSize != n) {
+                        Object[] newElements = new Object[len - n + newSize];
+                        System.arraycopy(elements, 0, newElements, 0, lo);
+                        System.arraycopy(temp, 0, newElements, lo, newSize);
+                        System.arraycopy(elements, hi, newElements,
+                                         lo + newSize, len - hi);
+                        size = newSize;
+                        removed = true;
+                        l.setArray(expectedArray = newElements);
+                    }
+                }
             } finally {
                 lock.unlock();
             }
+            return removed;
         }
 
-        @Override
-        public void replaceAll(UnaryOperator<E> operator) {
+        public boolean removeIf(Predicate<? super E> filter) {
+            if (filter == null) throw new NullPointerException();
+            boolean removed = false;
             final ReentrantLock lock = l.lock;
             lock.lock();
             try {
-                checkForComodification();
-                l.replaceAll(operator, offset, offset + size);
-                expectedArray = l.getArray();
+                int n = size;
+                if (n > 0) {
+                    int lo = offset;
+                    int hi = offset + n;
+                    Object[] elements = expectedArray;
+                    if (l.getArray() != elements)
+                        throw new ConcurrentModificationException();
+                    int len = elements.length;
+                    if (lo < 0 || hi > len)
+                        throw new IndexOutOfBoundsException();
+                    int newSize = 0;
+                    Object[] temp = new Object[n];
+                    for (int i = lo; i < hi; ++i) {
+                        @SuppressWarnings("unchecked") E e = (E) elements[i];
+                        if (!filter.test(e))
+                            temp[newSize++] = e;
+                    }
+                    if (newSize != n) {
+                        Object[] newElements = new Object[len - n + newSize];
+                        System.arraycopy(elements, 0, newElements, 0, lo);
+                        System.arraycopy(temp, 0, newElements, lo, newSize);
+                        System.arraycopy(elements, hi, newElements,
+                                         lo + newSize, len - hi);
+                        size = newSize;
+                        removed = true;
+                        l.setArray(expectedArray = newElements);
+                    }
+                }
             } finally {
                 lock.unlock();
             }
+            return removed;
+        }
+
+        public Spliterator<E> spliterator() {
+            int lo = offset;
+            int hi = offset + size;
+            Object[] a = expectedArray;
+            if (l.getArray() != a)
+                throw new ConcurrentModificationException();
+            if (lo < 0 || hi > a.length)
+                throw new IndexOutOfBoundsException();
+            return Spliterators.spliterator
+                (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
         }
     }
 
@@ -1380,11 +1636,12 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
-            while (nextIndex() < size) {
-                action.accept(it.next());
+            int s = size;
+            ListIterator<E> i = it;
+            while (nextIndex() < s) {
+                action.accept(i.next());
             }
         }
     }
@@ -1405,139 +1662,4 @@
             throw new Error(e);
         }
     }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public void forEach(Consumer<? super E> action) {
-        forEach(action, (E[]) getArray(), 0, size());
-    }
-
-    private void forEach(Consumer<? super E> action,
-                         final E[] elements,
-                         final int from, final int to) {
-        Objects.requireNonNull(action);
-        for (int i = from; i < to; i++) {
-            action.accept(elements[i]);
-        }
-    }
-
-    @Override
-    public void sort(Comparator<? super E> c) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            sort(c, 0, size());
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    // must be called with this.lock held
-    @SuppressWarnings("unchecked")
-    private void sort(Comparator<? super E> c, final int from, final int to) {
-        final E[] elements = (E[]) getArray();
-        final E[] newElements = Arrays.copyOf(elements, elements.length);
-        // only elements [from, to) are sorted
-        Arrays.sort(newElements, from, to, c);
-        setArray(newElements);
-    }
-
-    @Override
-    public boolean removeIf(Predicate<? super E> filter) {
-        Objects.requireNonNull(filter);
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return removeIf(filter, 0, size()) > 0;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    // must be called with this.lock held
-    private int removeIf(Predicate<? super E> filter, final int from, final int to) {
-        Objects.requireNonNull(filter);
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            @SuppressWarnings("unchecked")
-            final E[] elements = (E[]) getArray();
-
-            // figure out which elements are to be removed
-            // any exception thrown from the filter predicate at this stage
-            // will leave the collection unmodified
-            int removeCount = 0;
-            final int range = to - from;
-            final BitSet removeSet = new BitSet(range);
-            for (int i = 0; i < range; i++) {
-                final E element = elements[from + i];
-                if (filter.test(element)) {
-                    // removeSet is zero-based to keep its size small
-                    removeSet.set(i);
-                    removeCount++;
-                }
-            }
-
-            // copy surviving elements into a new array
-            if (removeCount > 0) {
-                final int newSize = elements.length - removeCount;
-                final int newRange = newSize - from;
-                @SuppressWarnings("unchecked")
-                final E[] newElements = (E[]) new Object[newSize];
-                // copy elements before [from, to) unmodified
-                for (int i = 0; i < from; i++) {
-                    newElements[i] = elements[i];
-                }
-                // elements [from, to) are subject to removal
-                int j = 0;
-                for (int i = 0; (i < range) && (j < newRange); i++) {
-                    i = removeSet.nextClearBit(i);
-                    if (i >= range) {
-                        break;
-                    }
-                    newElements[from + (j++)] = elements[from + i];
-                }
-                // copy any remaining elements beyond [from, to)
-                j += from;
-                for (int i = to; (i < elements.length) && (j < newSize); i++) {
-                    newElements[j++] = elements[i];
-                }
-                setArray(newElements);
-            }
-
-            return removeCount;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    @Override
-    public void replaceAll(UnaryOperator<E> operator) {
-        Objects.requireNonNull(operator);
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            replaceAll(operator, 0, size());
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    // must be called with this.lock held
-    @SuppressWarnings("unchecked")
-    private void replaceAll(UnaryOperator<E> operator, final int from, final int to) {
-        final E[] elements = (E[]) getArray();
-        final E[] newElements = (E[]) new Object[elements.length];
-        for (int i = 0; i < from; i++) {
-            newElements[i] = elements[i];
-        }
-        // the operator is only applied to elements [from, to)
-        for (int i = from; i < to; i++) {
-            newElements[i] = operator.apply(elements[i]);
-        }
-        for (int i = to; i < elements.length; i++) {
-            newElements[i] = elements[i];
-        }
-        setArray(newElements);
-    }
 }
--- a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java	Wed Jul 03 11:58:09 2013 +0200
@@ -34,7 +34,14 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
+import java.util.Collection;
+import java.util.Set;
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Predicate;
+import java.util.function.Consumer;
 
 /**
  * A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
@@ -45,17 +52,17 @@
  *       vastly outnumber mutative operations, and you need
  *       to prevent interference among threads during traversal.
  *  <li>It is thread-safe.
- *  <li>Mutative operations (<tt>add</tt>, <tt>set</tt>, <tt>remove</tt>, etc.)
+ *  <li>Mutative operations ({@code add}, {@code set}, {@code remove}, etc.)
  *      are expensive since they usually entail copying the entire underlying
  *      array.
- *  <li>Iterators do not support the mutative <tt>remove</tt> operation.
+ *  <li>Iterators do not support the mutative {@code remove} operation.
  *  <li>Traversal via iterators is fast and cannot encounter
  *      interference from other threads. Iterators rely on
  *      unchanging snapshots of the array at the time the iterators were
  *      constructed.
  * </ul>
  *
- * <p> <b>Sample Usage.</b> The following code sketch uses a
+ * <p><b>Sample Usage.</b> The following code sketch uses a
  * copy-on-write set to maintain a set of Handler objects that
  * perform some action upon state updates.
  *
@@ -73,7 +80,7 @@
  *   public void update() {
  *     changeState();
  *     for (Handler handler : handlers)
- *        handler.handle();
+ *       handler.handle();
  *   }
  * }}</pre>
  *
@@ -107,8 +114,15 @@
      * @throws NullPointerException if the specified collection is null
      */
     public CopyOnWriteArraySet(Collection<? extends E> c) {
-        al = new CopyOnWriteArrayList<E>();
-        al.addAllAbsent(c);
+        if (c.getClass() == CopyOnWriteArraySet.class) {
+            @SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
+                (CopyOnWriteArraySet<E>)c;
+            al = new CopyOnWriteArrayList<E>(cc.al);
+        }
+        else {
+            al = new CopyOnWriteArrayList<E>();
+            al.addAllAbsent(c);
+        }
     }
 
     /**
@@ -121,22 +135,22 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains no elements.
+     * Returns {@code true} if this set contains no elements.
      *
-     * @return <tt>true</tt> if this set contains no elements
+     * @return {@code true} if this set contains no elements
      */
     public boolean isEmpty() {
         return al.isEmpty();
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this set
-     * contains an element <tt>e</tt> such that
+     * Returns {@code true} if this set contains the specified element.
+     * More formally, returns {@code true} if and only if this set
+     * contains an element {@code e} such that
      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
      *
      * @param o element whose presence in this set is to be tested
-     * @return <tt>true</tt> if this set contains the specified element
+     * @return {@code true} if this set contains the specified element
      */
     public boolean contains(Object o) {
         return al.contains(o);
@@ -172,7 +186,7 @@
      * <p>If this set fits in the specified array with room to spare
      * (i.e., the array has more elements than this set), the element in
      * the array immediately following the end of the set is set to
-     * <tt>null</tt>.  (This is useful in determining the length of this
+     * {@code null}.  (This is useful in determining the length of this
      * set <i>only</i> if the caller knows that this set does not contain
      * any null elements.)
      *
@@ -185,14 +199,14 @@
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a set known to contain only strings.
+     * <p>Suppose {@code x} is a set known to contain only strings.
      * The following code can be used to dump the set into a newly allocated
-     * array of <tt>String</tt>:
+     * array of {@code String}:
      *
      *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of this set are to be
      *        stored, if it is big enough; otherwise, a new array of the same
@@ -217,15 +231,15 @@
 
     /**
      * Removes the specified element from this set if it is present.
-     * More formally, removes an element <tt>e</tt> such that
+     * More formally, removes an element {@code e} such that
      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
-     * if this set contains such an element.  Returns <tt>true</tt> if
+     * if this set contains such an element.  Returns {@code true} if
      * this set contained the element (or equivalently, if this set
      * changed as a result of the call).  (This set will not contain the
      * element once the call returns.)
      *
      * @param o object to be removed from this set, if present
-     * @return <tt>true</tt> if this set contained the specified element
+     * @return {@code true} if this set contained the specified element
      */
     public boolean remove(Object o) {
         return al.remove(o);
@@ -233,14 +247,14 @@
 
     /**
      * Adds the specified element to this set if it is not already present.
-     * More formally, adds the specified element <tt>e</tt> to this set if
-     * the set contains no element <tt>e2</tt> such that
+     * More formally, adds the specified element {@code e} to this set if
+     * the set contains no element {@code e2} such that
      * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
      * If this set already contains the element, the call leaves the set
-     * unchanged and returns <tt>false</tt>.
+     * unchanged and returns {@code false}.
      *
      * @param e element to be added to this set
-     * @return <tt>true</tt> if this set did not already contain the specified
+     * @return {@code true} if this set did not already contain the specified
      *         element
      */
     public boolean add(E e) {
@@ -248,12 +262,12 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains all of the elements of the
+     * Returns {@code true} if this set contains all of the elements of the
      * specified collection.  If the specified collection is also a set, this
-     * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
+     * method returns {@code true} if it is a <i>subset</i> of this set.
      *
      * @param  c collection to be checked for containment in this set
-     * @return <tt>true</tt> if this set contains all of the elements of the
+     * @return {@code true} if this set contains all of the elements of the
      *         specified collection
      * @throws NullPointerException if the specified collection is null
      * @see #contains(Object)
@@ -265,13 +279,13 @@
     /**
      * Adds all of the elements in the specified collection to this set if
      * they're not already present.  If the specified collection is also a
-     * set, the <tt>addAll</tt> operation effectively modifies this set so
+     * set, the {@code addAll} operation effectively modifies this set so
      * that its value is the <i>union</i> of the two sets.  The behavior of
      * this operation is undefined if the specified collection is modified
      * while the operation is in progress.
      *
      * @param  c collection containing elements to be added to this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws NullPointerException if the specified collection is null
      * @see #add(Object)
      */
@@ -286,7 +300,7 @@
      * <i>asymmetric set difference</i> of the two sets.
      *
      * @param  c collection containing elements to be removed from this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the class of an element of this set
      *         is incompatible with the specified collection (optional)
      * @throws NullPointerException if this set contains a null element and the
@@ -307,7 +321,7 @@
      * two sets.
      *
      * @param  c collection containing elements to be retained in this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the class of an element of this set
      *         is incompatible with the specified collection (optional)
      * @throws NullPointerException if this set contains a null element and the
@@ -326,7 +340,7 @@
      * <p>The returned iterator provides a snapshot of the state of the set
      * when the iterator was constructed. No synchronization is needed while
      * traversing the iterator. The iterator does <em>NOT</em> support the
-     * <tt>remove</tt> method.
+     * {@code remove} method.
      *
      * @return an iterator over the elements in this set
      */
@@ -338,7 +352,7 @@
      * Compares the specified object with this set for equality.
      * Returns {@code true} if the specified object is the same object
      * as this object, or if it is also a {@link Set} and the elements
-     * returned by an {@linkplain List#iterator() iterator} over the
+     * returned by an {@linkplain Set#iterator() iterator} over the
      * specified set are the same as the elements returned by an
      * iterator over this set.  More formally, the two iterators are
      * considered to return the same elements if they return the same
@@ -382,6 +396,19 @@
         return k == len;
     }
 
+    public boolean removeIf(Predicate<? super E> filter) {
+        return al.removeIf(filter);
+    }
+
+    public void forEach(Consumer<? super E> action) {
+        al.forEach(action);
+    }
+
+    public Spliterator<E> spliterator() {
+        return Spliterators.spliterator
+            (al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
+    }
+
     /**
      * Tests for equality, coping with nulls.
      */
--- a/jdk/src/share/classes/java/util/concurrent/DelayQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/DelayQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -33,28 +33,31 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
-
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.*;
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} of
- * <tt>Delayed</tt> elements, in which an element can only be taken
+ * {@code Delayed} elements, in which an element can only be taken
  * when its delay has expired.  The <em>head</em> of the queue is that
- * <tt>Delayed</tt> element whose delay expired furthest in the
- * past.  If no delay has expired there is no head and <tt>poll</tt>
- * will return <tt>null</tt>. Expiration occurs when an element's
- * <tt>getDelay(TimeUnit.NANOSECONDS)</tt> method returns a value less
+ * {@code Delayed} element whose delay expired furthest in the
+ * past.  If no delay has expired there is no head and {@code poll}
+ * will return {@code null}. Expiration occurs when an element's
+ * {@code getDelay(TimeUnit.NANOSECONDS)} method returns a value less
  * than or equal to zero.  Even though unexpired elements cannot be
- * removed using <tt>take</tt> or <tt>poll</tt>, they are otherwise
- * treated as normal elements. For example, the <tt>size</tt> method
+ * removed using {@code take} or {@code poll}, they are otherwise
+ * treated as normal elements. For example, the {@code size} method
  * returns the count of both expired and unexpired elements.
  * This queue does not permit null elements.
  *
  * <p>This class and its iterator implement all of the
  * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * Iterator} interfaces.  The Iterator provided in method {@link
+ * #iterator()} is <em>not</em> guaranteed to traverse the elements of
+ * the DelayQueue in any particular order.
  *
  * <p>This class is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -64,11 +67,10 @@
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
  */
-
 public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
     implements BlockingQueue<E> {
 
-    private transient final ReentrantLock lock = new ReentrantLock();
+    private final transient ReentrantLock lock = new ReentrantLock();
     private final PriorityQueue<E> q = new PriorityQueue<E>();
 
     /**
@@ -97,12 +99,12 @@
     private final Condition available = lock.newCondition();
 
     /**
-     * Creates a new <tt>DelayQueue</tt> that is initially empty.
+     * Creates a new {@code DelayQueue} that is initially empty.
      */
     public DelayQueue() {}
 
     /**
-     * Creates a <tt>DelayQueue</tt> initially containing the elements of the
+     * Creates a {@code DelayQueue} initially containing the elements of the
      * given collection of {@link Delayed} instances.
      *
      * @param c the collection of elements to initially contain
@@ -117,7 +119,7 @@
      * Inserts the specified element into this delay queue.
      *
      * @param e the element to add
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      * @throws NullPointerException if the specified element is null
      */
     public boolean add(E e) {
@@ -128,7 +130,7 @@
      * Inserts the specified element into this delay queue.
      *
      * @param e the element to add
-     * @return <tt>true</tt>
+     * @return {@code true}
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
@@ -164,7 +166,7 @@
      * @param e the element to add
      * @param timeout This parameter is ignored as the method never blocks
      * @param unit This parameter is ignored as the method never blocks
-     * @return <tt>true</tt>
+     * @return {@code true}
      * @throws NullPointerException {@inheritDoc}
      */
     public boolean offer(E e, long timeout, TimeUnit unit) {
@@ -172,10 +174,10 @@
     }
 
     /**
-     * Retrieves and removes the head of this queue, or returns <tt>null</tt>
+     * Retrieves and removes the head of this queue, or returns {@code null}
      * if this queue has no elements with an expired delay.
      *
-     * @return the head of this queue, or <tt>null</tt> if this
+     * @return the head of this queue, or {@code null} if this
      *         queue has no elements with an expired delay
      */
     public E poll() {
@@ -183,7 +185,7 @@
         lock.lock();
         try {
             E first = q.peek();
-            if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+            if (first == null || first.getDelay(NANOSECONDS) > 0)
                 return null;
             else
                 return q.poll();
@@ -208,10 +210,11 @@
                 if (first == null)
                     available.await();
                 else {
-                    long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                    long delay = first.getDelay(NANOSECONDS);
                     if (delay <= 0)
                         return q.poll();
-                    else if (leader != null)
+                    first = null; // don't retain ref while waiting
+                    if (leader != null)
                         available.await();
                     else {
                         Thread thisThread = Thread.currentThread();
@@ -237,7 +240,7 @@
      * until an element with an expired delay is available on this queue,
      * or the specified wait time expires.
      *
-     * @return the head of this queue, or <tt>null</tt> if the
+     * @return the head of this queue, or {@code null} if the
      *         specified waiting time elapses before an element with
      *         an expired delay becomes available
      * @throws InterruptedException {@inheritDoc}
@@ -255,11 +258,12 @@
                     else
                         nanos = available.awaitNanos(nanos);
                 } else {
-                    long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                    long delay = first.getDelay(NANOSECONDS);
                     if (delay <= 0)
                         return q.poll();
                     if (nanos <= 0)
                         return null;
+                    first = null; // don't retain ref while waiting
                     if (nanos < delay || leader != null)
                         nanos = available.awaitNanos(nanos);
                     else {
@@ -284,13 +288,13 @@
 
     /**
      * Retrieves, but does not remove, the head of this queue, or
-     * returns <tt>null</tt> if this queue is empty.  Unlike
-     * <tt>poll</tt>, if no expired elements are available in the queue,
+     * returns {@code null} if this queue is empty.  Unlike
+     * {@code poll}, if no expired elements are available in the queue,
      * this method returns the element that will expire next,
      * if one exists.
      *
-     * @return the head of this queue, or <tt>null</tt> if this
-     *         queue is empty.
+     * @return the head of this queue, or {@code null} if this
+     *         queue is empty
      */
     public E peek() {
         final ReentrantLock lock = this.lock;
@@ -313,6 +317,17 @@
     }
 
     /**
+     * Returns first element only if it is expired.
+     * Used only by drainTo.  Call only when holding lock.
+     */
+    private E peekExpired() {
+        // assert lock.isHeldByCurrentThread();
+        E first = q.peek();
+        return (first == null || first.getDelay(NANOSECONDS) > 0) ?
+            null : first;
+    }
+
+    /**
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
@@ -327,11 +342,9 @@
         lock.lock();
         try {
             int n = 0;
-            for (;;) {
-                E first = q.peek();
-                if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
-                    break;
-                c.add(q.poll());
+            for (E e; (e = peekExpired()) != null;) {
+                c.add(e);       // In this order, in case add() throws.
+                q.poll();
                 ++n;
             }
             return n;
@@ -357,11 +370,9 @@
         lock.lock();
         try {
             int n = 0;
-            while (n < maxElements) {
-                E first = q.peek();
-                if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
-                    break;
-                c.add(q.poll());
+            for (E e; n < maxElements && (e = peekExpired()) != null;) {
+                c.add(e);       // In this order, in case add() throws.
+                q.poll();
                 ++n;
             }
             return n;
@@ -387,10 +398,10 @@
     }
 
     /**
-     * Always returns <tt>Integer.MAX_VALUE</tt> because
-     * a <tt>DelayQueue</tt> is not capacity constrained.
+     * Always returns {@code Integer.MAX_VALUE} because
+     * a {@code DelayQueue} is not capacity constrained.
      *
-     * @return <tt>Integer.MAX_VALUE</tt>
+     * @return {@code Integer.MAX_VALUE}
      */
     public int remainingCapacity() {
         return Integer.MAX_VALUE;
@@ -430,7 +441,7 @@
      * <p>If this queue fits in the specified array with room to spare
      * (i.e., the array has more elements than this queue), the element in
      * the array immediately following the end of the queue is set to
-     * <tt>null</tt>.
+     * {@code null}.
      *
      * <p>Like the {@link #toArray()} method, this method acts as bridge between
      * array-based and collection-based APIs.  Further, this method allows
@@ -438,13 +449,12 @@
      * under certain circumstances, be used to save allocation costs.
      *
      * <p>The following code can be used to dump a delay queue into a newly
-     * allocated array of <tt>Delayed</tt>:
+     * allocated array of {@code Delayed}:
      *
-     * <pre>
-     *     Delayed[] a = q.toArray(new Delayed[0]);</pre>
+     * <pre> {@code Delayed[] a = q.toArray(new Delayed[0]);}</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the queue are to
      *          be stored, if it is big enough; otherwise, a new array of the
@@ -480,6 +490,24 @@
     }
 
     /**
+     * Identity-based version for use in Itr.remove
+     */
+    void removeEQ(Object o) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            for (Iterator<E> it = q.iterator(); it.hasNext(); ) {
+                if (o == it.next()) {
+                    it.remove();
+                    break;
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
      * Returns an iterator over all the elements (both expired and
      * unexpired) in this queue. The iterator does not return the
      * elements in any particular order.
@@ -502,7 +530,7 @@
      */
     private class Itr implements Iterator<E> {
         final Object[] array; // Array of all elements
-        int cursor;           // index of next element to return;
+        int cursor;           // index of next element to return
         int lastRet;          // index of last element, or -1 if no such
 
         Itr(Object[] array) {
@@ -525,21 +553,8 @@
         public void remove() {
             if (lastRet < 0)
                 throw new IllegalStateException();
-            Object x = array[lastRet];
+            removeEQ(array[lastRet]);
             lastRet = -1;
-            // Traverse underlying queue to find == element,
-            // not just a .equals element.
-            lock.lock();
-            try {
-                for (Iterator<E> it = q.iterator(); it.hasNext(); ) {
-                    if (it.next() == x) {
-                        it.remove();
-                        return;
-                    }
-                }
-            } finally {
-                lock.unlock();
-            }
         }
     }
 
--- a/jdk/src/share/classes/java/util/concurrent/Delayed.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/Delayed.java	Wed Jul 03 11:58:09 2013 +0200
@@ -40,8 +40,8 @@
  * acted upon after a given delay.
  *
  * <p>An implementation of this interface must define a
- * <tt>compareTo</tt> method that provides an ordering consistent with
- * its <tt>getDelay</tt> method.
+ * {@code compareTo} method that provides an ordering consistent with
+ * its {@code getDelay} method.
  *
  * @since 1.5
  * @author Doug Lea
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Wed Jul 03 11:58:09 2013 +0200
@@ -41,12 +41,15 @@
 import java.util.NoSuchElementException;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
 
 /**
  * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
  * linked nodes.
  *
- * <p> The optional capacity bound constructor argument serves as a
+ * <p>The optional capacity bound constructor argument serves as a
  * way to prevent excessive expansion. The capacity, if unspecified,
  * is equal to {@link Integer#MAX_VALUE}.  Linked nodes are
  * dynamically created upon each insertion unless this would bring the
@@ -315,8 +318,8 @@
     // BlockingDeque methods
 
     /**
-     * @throws IllegalStateException {@inheritDoc}
-     * @throws NullPointerException  {@inheritDoc}
+     * @throws IllegalStateException if this deque is full
+     * @throws NullPointerException {@inheritDoc}
      */
     public void addFirst(E e) {
         if (!offerFirst(e))
@@ -324,7 +327,7 @@
     }
 
     /**
-     * @throws IllegalStateException {@inheritDoc}
+     * @throws IllegalStateException if this deque is full
      * @throws NullPointerException  {@inheritDoc}
      */
     public void addLast(E e) {
@@ -623,8 +626,7 @@
      *
      * <p>This method is equivalent to {@link #addLast}.
      *
-     * @throws IllegalStateException if the element cannot be added at this
-     *         time due to capacity restrictions
+     * @throws IllegalStateException if this deque is full
      * @throws NullPointerException if the specified element is null
      */
     public boolean add(E e) {
@@ -761,8 +763,8 @@
     // Stack methods
 
     /**
-     * @throws IllegalStateException {@inheritDoc}
-     * @throws NullPointerException  {@inheritDoc}
+     * @throws IllegalStateException if this deque is full
+     * @throws NullPointerException {@inheritDoc}
      */
     public void push(E e) {
         addFirst(e);
@@ -852,7 +854,7 @@
 //      * @throws ClassCastException            {@inheritDoc}
 //      * @throws NullPointerException          {@inheritDoc}
 //      * @throws IllegalArgumentException      {@inheritDoc}
-//      * @throws IllegalStateException         {@inheritDoc}
+//      * @throws IllegalStateException if this deque is full
 //      * @see #add(Object)
 //      */
 //     public boolean addAll(Collection<? extends E> c) {
@@ -1151,6 +1153,127 @@
         Node<E> nextNode(Node<E> n) { return n.prev; }
     }
 
+    /** A customized variant of Spliterators.IteratorSpliterator */
+    static final class LBDSpliterator<E> implements Spliterator<E> {
+        static final int MAX_BATCH = 1 << 25;  // max batch array size;
+        final LinkedBlockingDeque<E> queue;
+        Node<E> current;    // current node; null until initialized
+        int batch;          // batch size for splits
+        boolean exhausted;  // true when no more nodes
+        long est;           // size estimate
+        LBDSpliterator(LinkedBlockingDeque<E> queue) {
+            this.queue = queue;
+            this.est = queue.size();
+        }
+
+        public long estimateSize() { return est; }
+
+        public Spliterator<E> trySplit() {
+            Node<E> h;
+            final LinkedBlockingDeque<E> q = this.queue;
+            int b = batch;
+            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
+            if (!exhausted &&
+                ((h = current) != null || (h = q.first) != null) &&
+                h.next != null) {
+                Object[] a = new Object[n];
+                final ReentrantLock lock = q.lock;
+                int i = 0;
+                Node<E> p = current;
+                lock.lock();
+                try {
+                    if (p != null || (p = q.first) != null) {
+                        do {
+                            if ((a[i] = p.item) != null)
+                                ++i;
+                        } while ((p = p.next) != null && i < n);
+                    }
+                } finally {
+                    lock.unlock();
+                }
+                if ((current = p) == null) {
+                    est = 0L;
+                    exhausted = true;
+                }
+                else if ((est -= i) < 0L)
+                    est = 0L;
+                if (i > 0) {
+                    batch = i;
+                    return Spliterators.spliterator
+                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                         Spliterator.CONCURRENT);
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            if (action == null) throw new NullPointerException();
+            final LinkedBlockingDeque<E> q = this.queue;
+            final ReentrantLock lock = q.lock;
+            if (!exhausted) {
+                exhausted = true;
+                Node<E> p = current;
+                do {
+                    E e = null;
+                    lock.lock();
+                    try {
+                        if (p == null)
+                            p = q.first;
+                        while (p != null) {
+                            e = p.item;
+                            p = p.next;
+                            if (e != null)
+                                break;
+                        }
+                    } finally {
+                        lock.unlock();
+                    }
+                    if (e != null)
+                        action.accept(e);
+                } while (p != null);
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            if (action == null) throw new NullPointerException();
+            final LinkedBlockingDeque<E> q = this.queue;
+            final ReentrantLock lock = q.lock;
+            if (!exhausted) {
+                E e = null;
+                lock.lock();
+                try {
+                    if (current == null)
+                        current = q.first;
+                    while (current != null) {
+                        e = current.item;
+                        current = current.next;
+                        if (e != null)
+                            break;
+                    }
+                } finally {
+                    lock.unlock();
+                }
+                if (current == null)
+                    exhausted = true;
+                if (e != null) {
+                    action.accept(e);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public int characteristics() {
+            return Spliterator.ORDERED | Spliterator.NONNULL |
+                Spliterator.CONCURRENT;
+        }
+    }
+
+    public Spliterator<E> spliterator() {
+        return new LBDSpliterator<E>(this);
+    }
+
     /**
      * Saves this deque to a stream (that is, serializes it).
      *
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -42,6 +42,9 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
 
 /**
  * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
@@ -56,7 +59,7 @@
  * Linked queues typically have higher throughput than array-based queues but
  * less predictable performance in most concurrent applications.
  *
- * <p> The optional capacity bound constructor argument serves as a
+ * <p>The optional capacity bound constructor argument serves as a
  * way to prevent excessive queue expansion. The capacity, if unspecified,
  * is equal to {@link Integer#MAX_VALUE}.  Linked nodes are
  * dynamically created upon each insertion unless this would bring the
@@ -216,7 +219,7 @@
     }
 
     /**
-     * Lock to prevent both puts and takes.
+     * Locks to prevent both puts and takes.
      */
     void fullyLock() {
         putLock.lock();
@@ -224,7 +227,7 @@
     }
 
     /**
-     * Unlock to allow both puts and takes.
+     * Unlocks to allow both puts and takes.
      */
     void fullyUnlock() {
         takeLock.unlock();
@@ -362,7 +365,7 @@
      * necessary up to the specified wait time for space to become available.
      *
      * @return {@code true} if successful, or {@code false} if
-     *         the specified waiting time elapses before space is available.
+     *         the specified waiting time elapses before space is available
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
      */
@@ -782,6 +785,7 @@
          * item to hand out so that if hasNext() reports true, we will
          * still have it to return even if lost race with a take etc.
          */
+
         private Node<E> current;
         private Node<E> lastRet;
         private E currentElement;
@@ -855,6 +859,124 @@
         }
     }
 
+    /** A customized variant of Spliterators.IteratorSpliterator */
+    static final class LBQSpliterator<E> implements Spliterator<E> {
+        static final int MAX_BATCH = 1 << 25;  // max batch array size;
+        final LinkedBlockingQueue<E> queue;
+        Node<E> current;    // current node; null until initialized
+        int batch;          // batch size for splits
+        boolean exhausted;  // true when no more nodes
+        long est;           // size estimate
+        LBQSpliterator(LinkedBlockingQueue<E> queue) {
+            this.queue = queue;
+            this.est = queue.size();
+        }
+
+        public long estimateSize() { return est; }
+
+        public Spliterator<E> trySplit() {
+            Node<E> h;
+            final LinkedBlockingQueue<E> q = this.queue;
+            int b = batch;
+            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
+            if (!exhausted &&
+                ((h = current) != null || (h = q.head.next) != null) &&
+                h.next != null) {
+                Object[] a = new Object[n];
+                int i = 0;
+                Node<E> p = current;
+                q.fullyLock();
+                try {
+                    if (p != null || (p = q.head.next) != null) {
+                        do {
+                            if ((a[i] = p.item) != null)
+                                ++i;
+                        } while ((p = p.next) != null && i < n);
+                    }
+                } finally {
+                    q.fullyUnlock();
+                }
+                if ((current = p) == null) {
+                    est = 0L;
+                    exhausted = true;
+                }
+                else if ((est -= i) < 0L)
+                    est = 0L;
+                if (i > 0) {
+                    batch = i;
+                    return Spliterators.spliterator
+                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                         Spliterator.CONCURRENT);
+                }
+            }
+            return null;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            if (action == null) throw new NullPointerException();
+            final LinkedBlockingQueue<E> q = this.queue;
+            if (!exhausted) {
+                exhausted = true;
+                Node<E> p = current;
+                do {
+                    E e = null;
+                    q.fullyLock();
+                    try {
+                        if (p == null)
+                            p = q.head.next;
+                        while (p != null) {
+                            e = p.item;
+                            p = p.next;
+                            if (e != null)
+                                break;
+                        }
+                    } finally {
+                        q.fullyUnlock();
+                    }
+                    if (e != null)
+                        action.accept(e);
+                } while (p != null);
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            if (action == null) throw new NullPointerException();
+            final LinkedBlockingQueue<E> q = this.queue;
+            if (!exhausted) {
+                E e = null;
+                q.fullyLock();
+                try {
+                    if (current == null)
+                        current = q.head.next;
+                    while (current != null) {
+                        e = current.item;
+                        current = current.next;
+                        if (e != null)
+                            break;
+                    }
+                } finally {
+                    q.fullyUnlock();
+                }
+                if (current == null)
+                    exhausted = true;
+                if (e != null) {
+                    action.accept(e);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public int characteristics() {
+            return Spliterator.ORDERED | Spliterator.NONNULL |
+                Spliterator.CONCURRENT;
+        }
+    }
+
+    public Spliterator<E> spliterator() {
+        return new LBQSpliterator<E>(this);
+    }
+
     /**
      * Saves this queue to a stream (that is, serializes it).
      *
--- a/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -40,8 +40,10 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.LockSupport;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
 
 /**
  * An unbounded {@link TransferQueue} based on linked nodes.
@@ -777,6 +779,24 @@
     }
 
     /**
+     * Version of firstOfMode used by Spliterator
+     */
+    final Node firstDataNode() {
+        for (Node p = head; p != null;) {
+            Object item = p.item;
+            if (p.isData) {
+                if (item != null && item != p)
+                    return p;
+            }
+            else if (item == null)
+                break;
+            if (p == (p = p.next))
+                p = head;
+        }
+        return null;
+    }
+
+    /**
      * Returns the item in the first unmatched node with isData; or
      * null if none.  Used by peek.
      */
@@ -910,6 +930,98 @@
         }
     }
 
+    /** A customized variant of Spliterators.IteratorSpliterator */
+    static final class LTQSpliterator<E> implements Spliterator<E> {
+        static final int MAX_BATCH = 1 << 25;  // max batch array size;
+        final LinkedTransferQueue<E> queue;
+        Node current;    // current node; null until initialized
+        int batch;          // batch size for splits
+        boolean exhausted;  // true when no more nodes
+        LTQSpliterator(LinkedTransferQueue<E> queue) {
+            this.queue = queue;
+        }
+
+        public Spliterator<E> trySplit() {
+            Node p;
+            final LinkedTransferQueue<E> q = this.queue;
+            int b = batch;
+            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.firstDataNode()) != null) &&
+                p.next != null) {
+                Object[] a = new Object[n];
+                int i = 0;
+                do {
+                    if ((a[i] = p.item) != null)
+                        ++i;
+                    if (p == (p = p.next))
+                        p = q.firstDataNode();
+                } while (p != null && i < n);
+                if ((current = p) == null)
+                    exhausted = true;
+                if (i > 0) {
+                    batch = i;
+                    return Spliterators.spliterator
+                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                         Spliterator.CONCURRENT);
+                }
+            }
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        public void forEachRemaining(Consumer<? super E> action) {
+            Node p;
+            if (action == null) throw new NullPointerException();
+            final LinkedTransferQueue<E> q = this.queue;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.firstDataNode()) != null)) {
+                exhausted = true;
+                do {
+                    Object e = p.item;
+                    if (p == (p = p.next))
+                        p = q.firstDataNode();
+                    if (e != null)
+                        action.accept((E)e);
+                } while (p != null);
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public boolean tryAdvance(Consumer<? super E> action) {
+            Node p;
+            if (action == null) throw new NullPointerException();
+            final LinkedTransferQueue<E> q = this.queue;
+            if (!exhausted &&
+                ((p = current) != null || (p = q.firstDataNode()) != null)) {
+                Object e;
+                do {
+                    e = p.item;
+                    if (p == (p = p.next))
+                        p = q.firstDataNode();
+                } while (e == null && p != null);
+                if ((current = p) == null)
+                    exhausted = true;
+                if (e != null) {
+                    action.accept((E)e);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public long estimateSize() { return Long.MAX_VALUE; }
+
+        public int characteristics() {
+            return Spliterator.ORDERED | Spliterator.NONNULL |
+                Spliterator.CONCURRENT;
+        }
+    }
+
+    public Spliterator<E> spliterator() {
+        return new LTQSpliterator<E>(this);
+    }
+
     /* -------------- Removal methods -------------- */
 
     /**
--- a/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -37,7 +37,17 @@
 
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
+import java.util.AbstractQueue;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.SortedSet;
+import java.util.Spliterator;
+import java.util.function.Consumer;
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} that uses
@@ -342,7 +352,6 @@
      * @param k the position to fill
      * @param x the item to insert
      * @param array the heap array
-     * @param n heap size
      */
     private static <T> void siftUpComparable(int k, T x, Object[] array) {
         Comparable<? super T> key = (Comparable<? super T>) x;
@@ -936,6 +945,70 @@
         }
     }
 
+    // Similar to Collections.ArraySnapshotSpliterator but avoids
+    // commitment to toArray until needed
+    static final class PBQSpliterator<E> implements Spliterator<E> {
+        final PriorityBlockingQueue<E> queue;
+        Object[] array;
+        int index;
+        int fence;
+
+        PBQSpliterator(PriorityBlockingQueue<E> queue, Object[] array,
+                       int index, int fence) {
+            this.queue = queue;
+            this.array = array;
+            this.index = index;
+            this.fence = fence;
+        }
+
+        final int getFence() {
+            int hi;
+            if ((hi = fence) < 0)
+                hi = fence = (array = queue.toArray()).length;
+            return hi;
+        }
+
+        public Spliterator<E> trySplit() {
+            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
+            return (lo >= mid) ? null :
+                new PBQSpliterator<E>(queue, array, lo, index = mid);
+        }
+
+        @SuppressWarnings("unchecked")
+        public void forEachRemaining(Consumer<? super E> action) {
+            Object[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if ((a = array) == null)
+                fence = (a = queue.toArray()).length;
+            if ((hi = fence) <= a.length &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do { action.accept((E)a[i]); } while (++i < hi);
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (getFence() > index && index >= 0) {
+                @SuppressWarnings("unchecked") E e = (E) array[index++];
+                action.accept(e);
+                return true;
+            }
+            return false;
+        }
+
+        public long estimateSize() { return (long)(getFence() - index); }
+
+        public int characteristics() {
+            return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED;
+        }
+    }
+
+    public Spliterator<E> spliterator() {
+        return new PBQSpliterator<E>(this, null, 0, -1);
+    }
+
     // Unsafe mechanics
     private static final sun.misc.Unsafe UNSAFE;
     private static final long allocationSpinLockOffset;
--- a/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java	Tue Jul 02 15:58:09 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java	Wed Jul 03 11:58:09 2013 +0200
@@ -44,17 +44,17 @@
  * operation must wait for a corresponding remove operation by another
  * thread, and vice versa.  A synchronous queue does not have any
  * internal capacity, not even a capacity of one.  You cannot
- * <tt>peek</tt> at a synchronous queue because an element is only
+ * {@code peek} at a synchronous queue because an element is only
  * present when you try to remove it; you cannot insert an element
  * (using any method) unless another thread is trying to remove it;
  * you cannot iterate as there is nothing to iterate.  The
  * <em>head</em> of the queue is the element that the first queued
  * inserting thread is trying to add to the queue; if there is no such
  * queued thread then no element is available for removal and
- * <tt>poll()</tt> will return <tt>null</tt>.  For purposes of other
- * <tt>Collection</tt> methods (for example <tt>contains</tt>), a
- * <tt>SynchronousQueue</tt> acts as an empty collection.  This queue
- * does not permit <tt>null</tt> elements.
+ * {@code poll()} will return {@code null}.  For purposes of other
+ * {@code Collection} methods (for example {@code contains}), a
+ * {@code SynchronousQueue} acts as an empty collection.  This queue
+ * does not permit {@code null} elements.
  *
  * <p>Synchronous queues are similar to rendezvous channels used in
  * CSP and Ada. They are well suited for handoff designs, in which an
@@ -62,10 +62,10 @@
  * in another thread in order to hand it some information, event, or
  * task.
  *
- * <p> This class supports an optional fairness policy for ordering
+ * <p>This class supports an optional fairness policy for ordering
  * waiting producer and consumer threads.  By default, this ordering
  * is not guaranteed. However, a queue constructed with fairness set
- * to <tt>true</tt> grants threads access in FIFO order.
+ * to {@code true} grants threads access in FIFO order.
  *
  * <p>This class and its iterator implement all of the
  * <em>optional</em> methods of the {@link Collection} and {@link
@@ -599,7 +599,7 @@
         /**
          * Reference to a cancelled node that might not yet have been
          * unlinked from queue because it was the last inserted node
-         * when it cancelled.
+         * when it was cancelled.
          */
         transient volatile QNode cleanMe;
 
@@ -847,14 +847,14 @@
     private transient volatile Transferer<E> transferer;
 
     /**
-     * Creates a <tt>SynchronousQueue</tt> with nonfair access policy.
+     * Creates a {@code SynchronousQueue} with nonfair access policy.
      */
     public SynchronousQueue() {
         this(false);
     }
 
     /**
-     * Creates a <tt>SynchronousQueue</tt> with the specified fairness policy.
+     * Creates a {@code SynchronousQueue} with the specified fairness policy.
      *
      * @param fair if true, waiting threads contend in FIFO order for
      *        access; otherwise the order is unspecified.
@@ -882,8 +882,8 @@
      * Inserts the specified element into this queue, waiting if necessary
      * up to the specified wait time for another thread to receive it.
      *
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if the
-     *         specified waiting time elapses before a consumer appears.
+     * @return {@code true} if successful, or {@code false} if the
+     *         specified waiting time elapses before a consumer appears
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
      */
@@ -902,8 +902,8 @@
      * waiting to receive it.
      *
      * @param e the element to add
-     * @return <tt>true</tt> if the element was added to this queue, else
-     *         <tt>false</tt>
+     * @return {@code true} if the element was added to this queue, else
+     *         {@code false}
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
@@ -931,8 +931,8 @@
      * if necessary up to the specified wait time, for another thread
      * to insert it.
      *
-     * @return the head of this queue, or <tt>null</tt> if the
-     *         specified waiting time elapses before an element is present.
+     * @return the head of this queue, or {@code null} if the
+     *         specified waiting time elapses before an element is present
      * @throws InterruptedException {@inheritDoc}
      */
     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
@@ -946,18 +946,18 @@
      * Retrieves and removes the head of this queue, if another thread
      * is currently making an element available.
      *
-     * @return the head of this queue, or <tt>null</tt> if no
-     *         element is available.
+     * @return the head of this queue, or {@code null} if no
+     *         element is available
      */
     public E poll() {
         return transferer.transfer(null, true, 0);
     }
 
     /**
-     * Always returns <tt>true</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code true}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
-     * @return <tt>true</tt>
+     * @return {@code true}
      */
     public boolean isEmpty() {
         return true;
@@ -965,9 +965,9 @@
 
     /**
      * Always returns zero.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
-     * @return zero.
+     * @return zero
      */
     public int size() {
         return 0;
@@ -975,9 +975,9 @@
 
     /**
      * Always returns zero.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
-     * @return zero.
+     * @return zero
      */
     public int remainingCapacity() {
         return 0;
@@ -985,80 +985,80 @@
 
     /**
      * Does nothing.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * A {@code SynchronousQueue} has no internal capacity.
      */
     public void clear() {
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param o the element
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean contains(Object o) {
         return false;
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param o the element to remove
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean remove(Object o) {
         return false;
     }
 
     /**
-     * Returns <tt>false</tt> unless the given collection is empty.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Returns {@code false} unless the given collection is empty.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param c the collection
-     * @return <tt>false</tt> unless given collection is empty
+     * @return {@code false} unless given collection is empty
      */
     public boolean containsAll(Collection<?> c) {
         return c.isEmpty();
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param c the collection
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean removeAll(Collection<?> c) {
         return false;
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param c the collection
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean retainAll(Collection<?> c) {
         return false;
     }
 
     /**
-     * Always returns <tt>null</tt>.
-     * A <tt>SynchronousQueue</tt> does not return elements
+     * Always returns {@code null}.
+     * A {@code SynchronousQueue} does not return elements
      * unless actively waited on.
      *
-     * @return <tt>null</tt>
+     * @return {@code null}
      */
     public E peek() {
         return null;
     }
 
     /**
-     * Returns an empty iterator in which <tt>hasNext</tt> always returns
-     * <tt>false</tt>.
+     * Returns an empty iterator in which {@code hasNext} always returns
+     * {@code false}.
      *
      * @return an empty iterator
      */
@@ -1077,6 +1077,10 @@
         public void remove() { throw new IllegalStateException(); }
     }
 
+    public Spliterator<E> spliterator() {
+        return Spliterators.emptySpliterator();
+    }
+
     /**
      * Returns a zero-length array.
      * @return a zero-length array
@@ -1086,7 +1090,7 @@
     }
 
     /**
-     * Sets the zeroeth element of the specified array to <tt>null</tt>
+     * Sets the zeroeth element of the specified array to {@code null}
      * (if the array has non-zero length) and returns it.
      *
      * @param a the array