changeset 7552:996188a59559

Updates to spliterators. Contributed-by: Doug Lea <dl@cs.oswego.edu>
author psandoz
date Fri, 01 Mar 2013 16:23:31 +0100
parents 4bf1ce19c7cd
children 45f88e5c6964
files src/share/classes/java/util/concurrent/ArrayBlockingQueue.java src/share/classes/java/util/concurrent/ConcurrentHashMap.java src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java src/share/classes/java/util/concurrent/LinkedBlockingDeque.java src/share/classes/java/util/concurrent/LinkedBlockingQueue.java src/share/classes/java/util/concurrent/LinkedTransferQueue.java src/share/classes/java/util/concurrent/PriorityBlockingQueue.java src/share/classes/java/util/concurrent/SynchronousQueue.java
diffstat 13 files changed, 424 insertions(+), 280 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Fri Mar 01 16:23:31 2013 +0100
@@ -34,7 +34,6 @@
  */
 
 package java.util.concurrent;
-import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.AbstractQueue;
@@ -42,6 +41,7 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.lang.ref.WeakReference;
+import java.util.Spliterators;
 import java.util.Spliterator;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Mar 01 16:23:31 2013 +0100
@@ -2173,15 +2173,12 @@
      * valid. To support iterator.remove, the nextKey field is not
      * updated (nulled out) when the iterator cannot advance.
      *
-     * Internal traversals directly access these fields, as in:
-     * {@code while (it.advance() != null) { process(it.nextKey); }}
-     *
      * Exported iterators must track whether the iterator has advanced
      * (in hasNext vs next) (by setting/checking/nulling field
      * nextVal), and then extract key, value, or key-value pairs as
      * return values of next().
      *
-     * The iterator visits once each still-valid node that was
+     * Method advance visits once each still-valid node that was
      * reachable upon iterator construction. It might miss some that
      * were added to a bin after the bin was visited, which is OK wrt
      * consistency guarantees. Maintaining this property in the face
@@ -2198,6 +2195,11 @@
      * across threads, iteration terminates if a bounds checks fails
      * for a table read.
      *
+     * Methods advanceKey and advanceValue are specializations of the
+     * common cases of advance, relaying to the full version
+     * otherwise. The forEachKey and forEachValue methods further
+     * specialize, bypassing all incremental field updates in most cases.
+     *
      * This class supports both Spliterator-based traversal and
      * CountedCompleter-based bulk tasks. The same "batch" field is
      * used, but in slightly different ways, in the two cases.  For
@@ -2225,14 +2227,14 @@
         int index;           // index of bin to use next
         int baseIndex;       // current index of initial table
         int baseLimit;       // index bound for initial table
-        int baseSize;        // initial table size
+        final int baseSize;  // initial table size
         int batch;           // split control
+
         /** Creates iterator for all entries in the table. */
         Traverser(ConcurrentHashMap<K,V> map) {
             this.map = map;
-            Node<V>[] t;
-            if ((t = tab = map.table) != null)
-                baseLimit = baseSize = t.length;
+            Node<V>[] t = this.tab = map.table;
+            baseLimit = baseSize = (t == null) ? 0 : t.length;
         }
 
         /** Task constructor */
@@ -2241,9 +2243,8 @@
             this.map = map;
             this.batch = batch; // -1 if unknown
             if (it == null) {
-                Node<V>[] t;
-                if ((t = tab = map.table) != null)
-                    baseLimit = baseSize = t.length;
+                Node<V>[] t = this.tab = map.table;
+                baseLimit = baseSize = (t == null) ? 0 : t.length;
             }
             else { // split parent
                 this.tab = it.tab;
@@ -2259,9 +2260,8 @@
             super(it);
             this.map = map;
             if (it == null) {
-                Node<V>[] t;
-                if ((t = tab = map.table) != null)
-                    baseLimit = baseSize = t.length;
+                Node<V>[] t = this.tab = map.table;
+                baseLimit = baseSize = (t == null) ? 0 : t.length;
                 long n = map.sumCount();
                 batch = ((n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :
                          (int)n);
@@ -2277,58 +2277,207 @@
         }
 
         /**
-         * Advances next; returns nextVal or null if terminated.
-         * See above for explanation.
+         * Advances if possible, returning next valid value, or null if none.
          */
         @SuppressWarnings("unchecked") final V advance() {
-            Node<V> e = next;
-            V ev = null;
-            outer: do {
+            for (Node<V> e = next;;) {
                 if (e != null)                  // advance past used/skipped node
-                    e = e.next;
+                    e = next = e.next;
                 while (e == null) {             // get to next non-null bin
-                    ConcurrentHashMap<K,V> m;
-                    Node<V>[] t; int b, i, n; Object ek; //  must use locals
-                    if ((t = tab) != null)
-                        n = t.length;
-                    else if ((m = map) != null && (t = tab = m.table) != null)
-                        n = baseLimit = baseSize = t.length;
-                    else
-                        break outer;
-                    if ((b = baseIndex) >= baseLimit ||
-                        (i = index) < 0 || i >= n)
-                        break outer;
-                    if ((e = tabAt(t, i)) != null && e.hash < 0) {
+                    Node<V>[] t; int i, n;      // must use locals in checks
+                    if (baseIndex >= baseLimit || (t = tab) == null ||
+                        (n = t.length) <= (i = index) || i < 0)
+                        return nextVal = null;
+                    if ((e = next = tabAt(t, index)) != null && e.hash < 0) {
+                        Object ek;
                         if ((ek = e.key) instanceof TreeBin)
                             e = ((TreeBin<V>)ek).first;
                         else {
                             tab = (Node<V>[])ek;
                             continue;           // restarts due to null val
                         }
-                    }                           // visit upper slots if present
-                    index = (i += baseSize) < n ? i : (baseIndex = b + 1);
+                    }
+                    if ((index += baseSize) >= n)
+                        index = ++baseIndex;    // visit upper slots if present
                 }
                 nextKey = (K)e.key;
-            } while ((ev = e.val) == null);    // skip deleted or special nodes
-            next = e;
-            return nextVal = ev;
+                if ((nextVal = e.val) != null) // skip deleted or special nodes
+                    return nextVal;
+            }
+        }
+
+        /**
+         * Common case version for value traversal
+         */
+        @SuppressWarnings("unchecked") final V advanceValue() {
+            outer: for (Node<V> e = next;;) {
+                if (e == null || (e = e.next) == null) {
+                    Node<V>[] t; int i, len, n; Object ek;
+                    if ((t = tab) == null ||
+                        baseSize != (len = t.length) ||
+                        len < (n = baseLimit) ||
+                        baseIndex != (i = index))
+                        break;
+                    do {
+                        if (i < 0 || i >= n) {
+                            index = baseIndex = n;
+                            next = null;
+                            return nextVal = null;
+                        }
+                        if ((e = tabAt(t, i)) != null && e.hash < 0) {
+                            if ((ek = e.key) instanceof TreeBin)
+                                e = ((TreeBin<V>)ek).first;
+                            else {
+                                index = baseIndex = i;
+                                next = null;
+                                tab = (Node<V>[])ek;
+                                break outer;
+                            }
+                        }
+                        ++i;
+                    } while (e == null);
+                    index = baseIndex = i;
+                }
+                V v;
+                K k = (K)e.key;
+                if ((v = e.val) != null) {
+                    nextVal = v;
+                    nextKey = k;
+                    next = e;
+                    return v;
+                }
+            }
+            return advance();
+        }
+
+        /**
+         * Common case version for key traversal
+         */
+        @SuppressWarnings("unchecked") final K advanceKey() {
+            outer: for (Node<V> e = next;;) {
+                if (e == null || (e = e.next) == null) {
+                    Node<V>[] t; int i, len, n; Object ek;
+                    if ((t = tab) == null ||
+                        baseSize != (len = t.length) ||
+                        len < (n = baseLimit) ||
+                        baseIndex != (i = index))
+                        break;
+                    do {
+                        if (i < 0 || i >= n) {
+                            index = baseIndex = n;
+                            next = null;
+                            nextVal = null;
+                            return null;
+                        }
+                        if ((e = tabAt(t, i)) != null && e.hash < 0) {
+                            if ((ek = e.key) instanceof TreeBin)
+                                e = ((TreeBin<V>)ek).first;
+                            else {
+                                index = baseIndex = i;
+                                next = null;
+                                tab = (Node<V>[])ek;
+                                break outer;
+                            }
+                        }
+                        ++i;
+                    } while (e == null);
+                    index = baseIndex = i;
+                }
+                V v;
+                K k = (K)e.key;
+                if ((v = e.val) != null) {
+                    nextVal = v;
+                    nextKey = k;
+                    next = e;
+                    return k;
+                }
+            }
+            return (advance() == null) ? null : nextKey;
+        }
+
+        @SuppressWarnings("unchecked") final void forEachValue(Consumer<? super V> action) {
+            if (action == null) throw new NullPointerException();
+            Node<V>[] t; int i, len, n;
+            if ((t = tab) != null && baseSize == (len = t.length) &&
+                len >= (n = baseLimit) && baseIndex == (i = index)) {
+                Node<V> e = next;
+                index = baseIndex = n;
+                next = null;
+                nextVal = null;
+                outer: for (;; e = e.next) {
+                    V v; Object ek;
+                    for (; e == null; ++i) {
+                        if (i < 0 || i >= n)
+                            return;
+                        if ((e = tabAt(t, i)) != null && e.hash < 0) {
+                            if ((ek = e.key) instanceof TreeBin)
+                                e = ((TreeBin<V>)ek).first;
+                            else {
+                                index = baseIndex = i;
+                                tab = (Node<V>[])ek;
+                                break outer;
+                            }
+                        }
+                    }
+                    if ((v = e.val) != null)
+                        action.accept(v);
+                }
+            }
+            V v;
+            while ((v = advance()) != null)
+                action.accept(v);
+        }
+
+        @SuppressWarnings("unchecked") final void forEachKey(Consumer<? super K> action) {
+            if (action == null) throw new NullPointerException();
+            Node<V>[] t; int i, len, n;
+            if ((t = tab) != null && baseSize == (len = t.length) &&
+                len >= (n = baseLimit) && baseIndex == (i = index)) {
+                Node<V> e = next;
+                index = baseIndex = n;
+                next = null;
+                nextVal = null;
+                outer: for (;; e = e.next) {
+                    for (; e == null; ++i) {
+                        if (i < 0 || i >= n)
+                            return;
+                        if ((e = tabAt(t, i)) != null && e.hash < 0) {
+                            Object ek;
+                            if ((ek = e.key) instanceof TreeBin)
+                                e = ((TreeBin<V>)ek).first;
+                            else {
+                                index = baseIndex = i;
+                                tab = (Node<V>[])ek;
+                                break outer;
+                            }
+                        }
+                    }
+                    Object k = e.key;
+                    if (e.val != null)
+                        action.accept((K)k);
+                }
+            }
+            while (advance() != null)
+                action.accept(nextKey);
         }
 
         public final void remove() {
             K k = nextKey;
-            if (k == null && (advance() == null || (k = nextKey) == null))
+            if (k == null && (advanceValue() == null || (k = nextKey) == null))
                 throw new IllegalStateException();
             map.internalReplace(k, null, null);
         }
 
         public final boolean hasNext() {
-            return nextVal != null || advance() != null;
+            return nextVal != null || advanceValue() != null;
         }
 
         public final boolean hasMoreElements() { return hasNext(); }
 
         public void compute() { } // default no-op CountedCompleter body
 
+        public long estimateSize() { return batch; }
+
         /**
          * Returns a batch value > 0 if this task should (and must) be
          * split, if so, adding to pending count, and in any case
@@ -2348,17 +2497,11 @@
                 long n = map.sumCount();
                 b = (n <= 0L) ? 0 : (n < (long)sp) ? (int)n : sp;
             }
-            b = (b <= 1 || baseIndex == baseLimit) ? 0 : (b >>> 1);
+            b = (b <= 1 || baseIndex >= baseLimit) ? 0 : (b >>> 1);
             if ((batch = b) > 0)
                 addToPendingCount(1);
             return b;
         }
-
-        // spliterator support
-
-        public long estimateSize() {
-            return batch;
-        }
     }
 
     /* ---------------- Public operations -------------- */
@@ -2537,7 +2680,7 @@
     /**
      * Tests if the specified object is a key in this table.
      *
-     * @param  key   possible key
+     * @param  key possible key
      * @return {@code true} if and only if the specified object
      *         is a key in this table, as determined by the
      *         {@code equals} method; {@code false} otherwise
@@ -2562,7 +2705,7 @@
             throw new NullPointerException();
         V v;
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if (v == value || value.equals(v))
                 return true;
         }
@@ -2881,7 +3024,7 @@
         int h = 0;
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             h += it.nextKey.hashCode() ^ v.hashCode();
         }
         return h;
@@ -2903,13 +3046,13 @@
         StringBuilder sb = new StringBuilder();
         sb.append('{');
         V v;
-        if ((v = it.advance()) != null) {
+        if ((v = it.advanceValue()) != null) {
             for (;;) {
                 K k = it.nextKey;
                 sb.append(k == this ? "(this Map)" : k);
                 sb.append('=');
                 sb.append(v == this ? "(this Map)" : v);
-                if ((v = it.advance()) == null)
+                if ((v = it.advanceValue()) == null)
                     break;
                 sb.append(',').append(' ');
             }
@@ -2934,7 +3077,7 @@
             Map<?,?> m = (Map<?,?>) o;
             Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
             V val;
-            while ((val = it.advance()) != null) {
+            while ((val = it.advanceValue()) != null) {
                 Object v = m.get(it.nextKey);
                 if (v == null || (v != val && !v.equals(val)))
                     return false;
@@ -2960,15 +3103,14 @@
         KeyIterator(ConcurrentHashMap<K,V> map, Traverser<K,V,Object> it) {
             super(map, it);
         }
-        public KeyIterator<K,V> trySplit() {
-            if (tab != null && baseIndex == baseLimit)
-                return null;
-            return new KeyIterator<K,V>(map, this);
+        public Spliterator<K> trySplit() {
+            return (baseIndex >= baseLimit) ? null :
+                new KeyIterator<K,V>(map, this);
         }
         public final K next() {
-            if (nextVal == null && advance() == null)
+            K k;
+            if ((k = (nextVal == null) ? advanceKey() : nextKey) == null)
                 throw new NoSuchElementException();
-            K k = nextKey;
             nextVal = null;
             return k;
         }
@@ -2978,21 +3120,20 @@
         public Iterator<K> iterator() { return this; }
 
         public void forEach(Consumer<? super K> action) {
-            if (action == null) throw new NullPointerException();
-            while (advance() != null)
-                action.accept(nextKey);
+            forEachKey(action);
         }
 
         public boolean tryAdvance(Consumer<? super K> block) {
             if (block == null) throw new NullPointerException();
-            if (advance() == null)
+            K k;
+            if ((k = advanceKey()) == null)
                 return false;
-            block.accept(nextKey);
+            block.accept(k);
             return true;
         }
 
         public int characteristics() {
-            return Spliterator.DISTINCT | Spliterator.CONCURRENT | 
+            return Spliterator.DISTINCT | Spliterator.CONCURRENT |
                 Spliterator.NONNULL;
         }
 
@@ -3005,15 +3146,14 @@
         ValueIterator(ConcurrentHashMap<K,V> map, Traverser<K,V,Object> it) {
             super(map, it);
         }
-        public ValueIterator<K,V> trySplit() {
-            if (tab != null && baseIndex == baseLimit)
-                return null;
-            return new ValueIterator<K,V>(map, this);
+        public Spliterator<V> trySplit() {
+            return (baseIndex >= baseLimit) ? null :
+                new ValueIterator<K,V>(map, this);
         }
 
         public final V next() {
             V v;
-            if ((v = nextVal) == null && (v = advance()) == null)
+            if ((v = nextVal) == null && (v = advanceValue()) == null)
                 throw new NoSuchElementException();
             nextVal = null;
             return v;
@@ -3024,16 +3164,13 @@
         public Iterator<V> iterator() { return this; }
 
         public void forEach(Consumer<? super V> action) {
-            if (action == null) throw new NullPointerException();
-            V v;
-            while ((v = advance()) != null)
-                action.accept(v);
+            forEachValue(action);
         }
 
         public boolean tryAdvance(Consumer<? super V> block) {
             V v;
             if (block == null) throw new NullPointerException();
-            if ((v = advance()) == null)
+            if ((v = advanceValue()) == null)
                 return false;
             block.accept(v);
             return true;
@@ -3051,15 +3188,14 @@
         EntryIterator(ConcurrentHashMap<K,V> map, Traverser<K,V,Object> it) {
             super(map, it);
         }
-        public EntryIterator<K,V> trySplit() {
-            if (tab != null && baseIndex == baseLimit)
-                return null;
-            return new EntryIterator<K,V>(map, this);
+        public Spliterator<Map.Entry<K,V>> trySplit() {
+            return (baseIndex >= baseLimit) ? null :
+                new EntryIterator<K,V>(map, this);
         }
 
         public final Map.Entry<K,V> next() {
             V v;
-            if ((v = nextVal) == null && (v = advance()) == null)
+            if ((v = nextVal) == null && (v = advanceValue()) == null)
                 throw new NoSuchElementException();
             K k = nextKey;
             nextVal = null;
@@ -3071,21 +3207,21 @@
         public void forEach(Consumer<? super Map.Entry<K,V>> action) {
             if (action == null) throw new NullPointerException();
             V v;
-            while ((v = advance()) != null)
+            while ((v = advanceValue()) != null)
                 action.accept(entryFor(nextKey, v));
         }
 
         public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> block) {
             V v;
             if (block == null) throw new NullPointerException();
-            if ((v = advance()) == null)
+            if ((v = advanceValue()) == null)
                 return false;
             block.accept(entryFor(nextKey, v));
             return true;
         }
 
         public int characteristics() {
-            return Spliterator.DISTINCT | Spliterator.CONCURRENT | 
+            return Spliterator.DISTINCT | Spliterator.CONCURRENT |
                 Spliterator.NONNULL;
         }
     }
@@ -3174,7 +3310,7 @@
         s.defaultWriteObject();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             s.writeObject(it.nextKey);
             s.writeObject(v);
         }
@@ -3279,7 +3415,7 @@
         if (action == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             action.accept(it.nextKey, v);
     }
 
@@ -3299,7 +3435,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v; U u;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = transformer.apply(it.nextKey, v)) != null)
                 action.accept(u);
         }
@@ -3319,7 +3455,7 @@
         if (searchFunction == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v; U u;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = searchFunction.apply(it.nextKey, v)) != null)
                 return u;
         }
@@ -3345,7 +3481,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         U r = null, u; V v;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = transformer.apply(it.nextKey, v)) != null)
                 r = (r == null) ? u : reducer.apply(r, u);
         }
@@ -3372,7 +3508,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         double r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsDouble(r, transformer.applyAsDouble(it.nextKey, v));
         return r;
     }
@@ -3397,7 +3533,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         long r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsLong(r, transformer.applyAsLong(it.nextKey, v));
         return r;
     }
@@ -3422,7 +3558,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         int r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsInt(r, transformer.applyAsInt(it.nextKey, v));
         return r;
     }
@@ -3434,10 +3570,7 @@
      */
     public void forEachKeySequentially
         (Consumer<? super K> action) {
-        if (action == null) throw new NullPointerException();
-        Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        while (it.advance() != null)
-            action.accept(it.nextKey);
+        new Traverser<K,V,Object>(this).forEachKey(action);
     }
 
     /**
@@ -3455,9 +3588,9 @@
         if (transformer == null || action == null)
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        U u;
-        while (it.advance() != null) {
-            if ((u = transformer.apply(it.nextKey)) != null)
+        K k; U u;
+        while ((k = it.advanceKey()) != null) {
+            if ((u = transformer.apply(k)) != null)
                 action.accept(u);
         }
         ForkJoinTasks.forEachKey
@@ -3476,9 +3609,9 @@
     public <U> U searchKeysSequentially
         (Function<? super K, ? extends U> searchFunction) {
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        U u;
-        while (it.advance() != null) {
-            if ((u = searchFunction.apply(it.nextKey)) != null)
+        K k; U u;
+        while ((k = it.advanceKey()) != null) {
+            if ((u = searchFunction.apply(k)) != null)
                 return u;
         }
         return null;
@@ -3496,9 +3629,8 @@
         (BiFunction<? super K, ? super K, ? extends K> reducer) {
         if (reducer == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        K r = null;
-        while (it.advance() != null) {
-            K u = it.nextKey;
+        K u, r = null;
+        while ((u = it.advanceKey()) != null) {
             r = (r == null) ? u : reducer.apply(r, u);
         }
         return r;
@@ -3522,9 +3654,9 @@
         if (transformer == null || reducer == null)
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        U r = null, u;
-        while (it.advance() != null) {
-            if ((u = transformer.apply(it.nextKey)) != null)
+        K k; U r = null, u;
+        while ((k = it.advanceKey()) != null) {
+            if ((u = transformer.apply(k)) != null)
                 r = (r == null) ? u : reducer.apply(r, u);
         }
         return r;
@@ -3550,8 +3682,9 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         double r = basis;
-        while (it.advance() != null)
-            r = reducer.applyAsDouble(r, transformer.applyAsDouble(it.nextKey));
+        K k;
+        while ((k = it.advanceKey()) != null)
+            r = reducer.applyAsDouble(r, transformer.applyAsDouble(k));
         return r;
     }
 
@@ -3575,8 +3708,9 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         long r = basis;
-        while (it.advance() != null)
-            r = reducer.applyAsLong(r, transformer.applyAsLong(it.nextKey));
+        K k;
+        while ((k = it.advanceKey()) != null)
+            r = reducer.applyAsLong(r, transformer.applyAsLong(k));
         return r;
     }
 
@@ -3600,8 +3734,9 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         int r = basis;
-        while (it.advance() != null)
-            r = reducer.applyAsInt(r, transformer.applyAsInt(it.nextKey));
+        K k;
+        while ((k = it.advanceKey()) != null)
+            r = reducer.applyAsInt(r, transformer.applyAsInt(k));
         return r;
     }
 
@@ -3611,11 +3746,7 @@
      * @param action the action
      */
     public void forEachValueSequentially(Consumer<? super V> action) {
-        if (action == null) throw new NullPointerException();
-        Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
-        V v;
-        while ((v = it.advance()) != null)
-            action.accept(v);
+        new Traverser<K,V,Object>(this).forEachValue(action);
     }
 
     /**
@@ -3634,7 +3765,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v; U u;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = transformer.apply(v)) != null)
                 action.accept(u);
         }
@@ -3654,7 +3785,7 @@
         if (searchFunction == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v; U u;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = searchFunction.apply(v)) != null)
                 return u;
         }
@@ -3673,7 +3804,7 @@
         if (reducer == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V r = null; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = (r == null) ? v : reducer.apply(r, v);
         return r;
     }
@@ -3697,7 +3828,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         U r = null, u; V v;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = transformer.apply(v)) != null)
                 r = (r == null) ? u : reducer.apply(r, u);
         }
@@ -3724,7 +3855,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         double r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsDouble(r, transformer.applyAsDouble(v));
         return r;
     }
@@ -3749,7 +3880,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         long r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsLong(r, transformer.applyAsLong(v));
         return r;
     }
@@ -3774,7 +3905,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         int r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsInt(r, transformer.applyAsInt(v));
         return r;
     }
@@ -3789,7 +3920,7 @@
         if (action == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             action.accept(entryFor(it.nextKey, v));
     }
 
@@ -3809,7 +3940,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v; U u;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = transformer.apply(entryFor(it.nextKey, v))) != null)
                 action.accept(u);
         }
@@ -3829,7 +3960,7 @@
         if (searchFunction == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         V v; U u;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = searchFunction.apply(entryFor(it.nextKey, v))) != null)
                 return u;
         }
@@ -3848,7 +3979,7 @@
         if (reducer == null) throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         Map.Entry<K,V> r = null; V v;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             Map.Entry<K,V> u = entryFor(it.nextKey, v);
             r = (r == null) ? u : reducer.apply(r, u);
         }
@@ -3874,7 +4005,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         U r = null, u; V v;
-        while ((v = it.advance()) != null) {
+        while ((v = it.advanceValue()) != null) {
             if ((u = transformer.apply(entryFor(it.nextKey, v))) != null)
                 r = (r == null) ? u : reducer.apply(r, u);
         }
@@ -3901,7 +4032,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         double r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsDouble(r, transformer.applyAsDouble(entryFor(it.nextKey, v)));
         return r;
     }
@@ -3926,7 +4057,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         long r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsLong(r, transformer.applyAsLong(entryFor(it.nextKey, v)));
         return r;
     }
@@ -3951,7 +4082,7 @@
             throw new NullPointerException();
         Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
         int r = basis; V v;
-        while ((v = it.advance()) != null)
+        while ((v = it.advanceValue()) != null)
             r = reducer.applyAsInt(r, transformer.applyAsInt(entryFor(it.nextKey, v)));
         return r;
     }
@@ -4768,11 +4899,15 @@
             return added;
         }
 
+        Spliterator<K> spliterator() {
+            return new KeyIterator<>(map, null);
+        }
+
         public Stream<K> stream() {
-            return Streams.stream(new KeyIterator<>(map, null));
+            return Streams.stream(spliterator());
         }
         public Stream<K> parallelStream() {
-            return Streams.parallelStream(new KeyIterator<K,V>(map, null));
+            return Streams.parallelStream(spliterator());
         }
     }
 
@@ -4823,12 +4958,16 @@
             throw new UnsupportedOperationException();
         }
 
+        Spliterator<V> spliterator() {
+            return new ValueIterator<K,V>(map, null);
+        }
+
         public Stream<V> stream() {
-            return Streams.stream(new ValueIterator<K,V>(map, null));
+            return Streams.stream(spliterator());
         }
 
         public Stream<V> parallelStream() {
-            return Streams.parallelStream(new ValueIterator<K,V>(map, null));
+            return Streams.parallelStream(spliterator());
         }
 
     }
@@ -4895,12 +5034,16 @@
             return added;
         }
 
+        Spliterator<Map.Entry<K,V>> spliterator() {
+            return new EntryIterator<K,V>(map, null);
+        }
+
         public Stream<Map.Entry<K,V>> stream() {
-            return Streams.stream(new EntryIterator<K,V>(map, null));
+            return Streams.stream(spliterator());
         }
 
         public Stream<Map.Entry<K,V>> parallelStream() {
-            return Streams.parallelStream(new EntryIterator<K,V>(map, null));
+            return Streams.parallelStream(spliterator());
         }
     }
 
@@ -5598,8 +5741,7 @@
             if ((action = this.action) != null) {
                 for (int b; (b = preSplit()) > 0;)
                     new ForEachKeyTask<K,V>(map, this, b, action).fork();
-                while (advance() != null)
-                    action.accept(nextKey);
+                forEachKey(action);
                 propagateCompletion();
             }
         }
@@ -5619,9 +5761,7 @@
             if ((action = this.action) != null) {
                 for (int b; (b = preSplit()) > 0;)
                     new ForEachValueTask<K,V>(map, this, b, action).fork();
-                V v;
-                while ((v = advance()) != null)
-                    action.accept(v);
+                forEachValue(action);
                 propagateCompletion();
             }
         }
@@ -5642,7 +5782,7 @@
                 for (int b; (b = preSplit()) > 0;)
                     new ForEachEntryTask<K,V>(map, this, b, action).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     action.accept(entryFor(nextKey, v));
                 propagateCompletion();
             }
@@ -5664,7 +5804,7 @@
                 for (int b; (b = preSplit()) > 0;)
                     new ForEachMappingTask<K,V>(map, this, b, action).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     action.accept(nextKey, v);
                 propagateCompletion();
             }
@@ -5689,9 +5829,9 @@
                 for (int b; (b = preSplit()) > 0;)
                     new ForEachTransformedKeyTask<K,V,U>
                         (map, this, b, transformer, action).fork();
-                U u;
-                while (advance() != null) {
-                    if ((u = transformer.apply(nextKey)) != null)
+                K k; U u;
+                while ((k = advanceKey()) != null) {
+                    if ((u = transformer.apply(k)) != null)
                         action.accept(u);
                 }
                 propagateCompletion();
@@ -5718,7 +5858,7 @@
                     new ForEachTransformedValueTask<K,V,U>
                         (map, this, b, transformer, action).fork();
                 V v; U u;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     if ((u = transformer.apply(v)) != null)
                         action.accept(u);
                 }
@@ -5746,7 +5886,7 @@
                     new ForEachTransformedEntryTask<K,V,U>
                         (map, this, b, transformer, action).fork();
                 V v; U u;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     if ((u = transformer.apply(entryFor(nextKey,
                                                         v))) != null)
                         action.accept(u);
@@ -5776,7 +5916,7 @@
                     new ForEachTransformedMappingTask<K,V,U>
                         (map, this, b, transformer, action).fork();
                 V v; U u;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     if ((u = transformer.apply(nextKey, v)) != null)
                         action.accept(u);
                 }
@@ -5811,12 +5951,12 @@
                         (map, this, b, searchFunction, result).fork();
                 }
                 while (result.get() == null) {
-                    U u;
-                    if (advance() == null) {
+                    K k; U u;
+                    if ((k = advanceKey()) == null) {
                         propagateCompletion();
                         break;
                     }
-                    if ((u = searchFunction.apply(nextKey)) != null) {
+                    if ((u = searchFunction.apply(k)) != null) {
                         if (result.compareAndSet(null, u))
                             quietlyCompleteRoot();
                         break;
@@ -5853,7 +5993,7 @@
                 }
                 while (result.get() == null) {
                     V v; U u;
-                    if ((v = advance()) == null) {
+                    if ((v = advanceValue()) == null) {
                         propagateCompletion();
                         break;
                     }
@@ -5894,7 +6034,7 @@
                 }
                 while (result.get() == null) {
                     V v; U u;
-                    if ((v = advance()) == null) {
+                    if ((v = advanceValue()) == null) {
                         propagateCompletion();
                         break;
                     }
@@ -5936,7 +6076,7 @@
                 }
                 while (result.get() == null) {
                     V v; U u;
-                    if ((v = advance()) == null) {
+                    if ((v = advanceValue()) == null) {
                         propagateCompletion();
                         break;
                     }
@@ -5969,9 +6109,8 @@
                 for (int b; (b = preSplit()) > 0;)
                     (rights = new ReduceKeysTask<K,V>
                      (map, this, b, rights, reducer)).fork();
-                K r = null;
-                while (advance() != null) {
-                    K u = nextKey;
+                K u, r = null;
+                while ((u = advanceKey()) != null) {
                     r = (r == null) ? u : u == null ? r : reducer.apply(r, u);
                 }
                 result = r;
@@ -6012,7 +6151,7 @@
                     (rights = new ReduceValuesTask<K,V>
                      (map, this, b, rights, reducer)).fork();
                 V r = null, v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = (r == null) ? v : reducer.apply(r, v);
                 result = r;
                 CountedCompleter<?> c;
@@ -6053,7 +6192,7 @@
                      (map, this, b, rights, reducer)).fork();
                 Map.Entry<K,V> r = null;
                 V v;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     Map.Entry<K,V> u = entryFor(nextKey, v);
                     r = (r == null) ? u : reducer.apply(r, u);
                 }
@@ -6099,9 +6238,9 @@
                 for (int b; (b = preSplit()) > 0;)
                     (rights = new MapReduceKeysTask<K,V,U>
                      (map, this, b, rights, transformer, reducer)).fork();
-                U r = null, u;
-                while (advance() != null) {
-                    if ((u = transformer.apply(nextKey)) != null)
+                K k; U r = null, u;
+                while ((k = advanceKey()) != null) {
+                    if ((u = transformer.apply(k)) != null)
                         r = (r == null) ? u : reducer.apply(r, u);
                 }
                 result = r;
@@ -6148,7 +6287,7 @@
                      (map, this, b, rights, transformer, reducer)).fork();
                 U r = null, u;
                 V v;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     if ((u = transformer.apply(v)) != null)
                         r = (r == null) ? u : reducer.apply(r, u);
                 }
@@ -6196,7 +6335,7 @@
                      (map, this, b, rights, transformer, reducer)).fork();
                 U r = null, u;
                 V v;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     if ((u = transformer.apply(entryFor(nextKey,
                                                         v))) != null)
                         r = (r == null) ? u : reducer.apply(r, u);
@@ -6245,7 +6384,7 @@
                      (map, this, b, rights, transformer, reducer)).fork();
                 U r = null, u;
                 V v;
-                while ((v = advance()) != null) {
+                while ((v = advanceValue()) != null) {
                     if ((u = transformer.apply(nextKey, v)) != null)
                         r = (r == null) ? u : reducer.apply(r, u);
                 }
@@ -6294,8 +6433,9 @@
                 for (int b; (b = preSplit()) > 0;)
                     (rights = new MapReduceKeysToDoubleTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
-                while (advance() != null)
-                    r = reducer.applyAsDouble(r, transformer.applyAsDouble(nextKey));
+                K k;
+                while ((k = advanceKey()) != null)
+                    r = reducer.applyAsDouble(r, transformer.applyAsDouble(k));
                 result = r;
                 CountedCompleter<?> c;
                 for (c = firstComplete(); c != null; c = c.nextComplete()) {
@@ -6339,7 +6479,7 @@
                     (rights = new MapReduceValuesToDoubleTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsDouble(r, transformer.applyAsDouble(v));
                 result = r;
                 CountedCompleter<?> c;
@@ -6384,7 +6524,7 @@
                     (rights = new MapReduceEntriesToDoubleTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsDouble(r, transformer.applyAsDouble(entryFor(nextKey,
                                                                     v)));
                 result = r;
@@ -6430,7 +6570,7 @@
                     (rights = new MapReduceMappingsToDoubleTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsDouble(r, transformer.applyAsDouble(nextKey, v));
                 result = r;
                 CountedCompleter<?> c;
@@ -6474,8 +6614,9 @@
                 for (int b; (b = preSplit()) > 0;)
                     (rights = new MapReduceKeysToLongTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
-                while (advance() != null)
-                    r = reducer.applyAsLong(r, transformer.applyAsLong(nextKey));
+                K k;
+                while ((k = advanceKey()) != null)
+                    r = reducer.applyAsLong(r, transformer.applyAsLong(k));
                 result = r;
                 CountedCompleter<?> c;
                 for (c = firstComplete(); c != null; c = c.nextComplete()) {
@@ -6519,7 +6660,7 @@
                     (rights = new MapReduceValuesToLongTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsLong(r, transformer.applyAsLong(v));
                 result = r;
                 CountedCompleter<?> c;
@@ -6564,7 +6705,7 @@
                     (rights = new MapReduceEntriesToLongTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsLong(r, transformer.applyAsLong(entryFor(nextKey, v)));
                 result = r;
                 CountedCompleter<?> c;
@@ -6609,7 +6750,7 @@
                     (rights = new MapReduceMappingsToLongTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsLong(r, transformer.applyAsLong(nextKey, v));
                 result = r;
                 CountedCompleter<?> c;
@@ -6653,8 +6794,9 @@
                 for (int b; (b = preSplit()) > 0;)
                     (rights = new MapReduceKeysToIntTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
-                while (advance() != null)
-                    r = reducer.applyAsInt(r, transformer.applyAsInt(nextKey));
+                K k;
+                while ((k = advanceKey()) != null)
+                    r = reducer.applyAsInt(r, transformer.applyAsInt(k));
                 result = r;
                 CountedCompleter<?> c;
                 for (c = firstComplete(); c != null; c = c.nextComplete()) {
@@ -6698,7 +6840,7 @@
                     (rights = new MapReduceValuesToIntTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsInt(r, transformer.applyAsInt(v));
                 result = r;
                 CountedCompleter<?> c;
@@ -6743,7 +6885,7 @@
                     (rights = new MapReduceEntriesToIntTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsInt(r, transformer.applyAsInt(entryFor(nextKey,
                                                                     v)));
                 result = r;
@@ -6789,7 +6931,7 @@
                     (rights = new MapReduceMappingsToIntTask<K,V>
                      (map, this, b, rights, transformer, r, reducer)).fork();
                 V v;
-                while ((v = advance()) != null)
+                while ((v = advanceValue()) != null)
                     r = reducer.applyAsInt(r, transformer.applyAsInt(nextKey, v));
                 result = r;
                 CountedCompleter<?> c;
--- a/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Fri Mar 01 16:23:31 2013 +0100
@@ -44,9 +44,9 @@
 import java.util.Queue;
 import java.util.Spliterator;
 import java.util.Spliterators;
-import java.util.function.Consumer;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
+import java.util.function.Consumer;
 
 /**
  * An unbounded concurrent {@linkplain Deque deque} based on linked nodes.
@@ -1406,19 +1406,23 @@
             final ConcurrentLinkedDeque<E> q = this.queue;
             if (!exhausted && (n = batch + 1) > 0 && n <= MAX_BATCH &&
                 ((p = current) != null || (p = q.first()) != null)) {
-                Object[] a = new Object[batch = 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;
-                return Spliterators.spliterator
-                    (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                     Spliterator.CONCURRENT);
+                if (p.item == null && p == (p = p.next))
+                    current = p = q.first();
+                if (p.next != null) {
+                    Object[] a = new Object[batch = 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;
+                    return Spliterators.spliterator
+                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                         Spliterator.CONCURRENT);
+                }
             }
             return null;
         }
@@ -1462,6 +1466,8 @@
             return false;
         }
 
+        public long estimateSize() { return Long.MAX_VALUE; }
+
         public int characteristics() {
             return Spliterator.ORDERED | Spliterator.NONNULL |
                 Spliterator.CONCURRENT;
--- a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Fri Mar 01 16:23:31 2013 +0100
@@ -807,8 +807,8 @@
             this.queue = queue;
         }
 
-        /*
-         * Split into arrays of arithmetically increasing batch sizes,
+        /**
+         * Splits into arrays of arithmetically increasing batch sizes,
          * giving up at MAX_BATCH.  This will only improve parallel
          * performance if per-element forEach actions are more costly
          * than transfering them into an array. If not, we limit
@@ -818,7 +818,8 @@
             Node<E> p; int n;
             final ConcurrentLinkedQueue<E> q = this.queue;
             if (!exhausted && (n = batch + 1) > 0 && n <= MAX_BATCH &&
-                ((p = current) != null || (p = q.first()) != null)) {
+                ((p = current) != null || (p = q.first()) != null) &&
+                p.next != null) {
                 Object[] a = new Object[batch = n];
                 int i = 0;
                 do {
@@ -830,8 +831,8 @@
                 if ((current = p) == null)
                     exhausted = true;
                 return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                                  Spliterator.CONCURRENT);
+                    (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                     Spliterator.CONCURRENT);
             }
             return null;
         }
@@ -875,6 +876,8 @@
             return false;
         }
 
+        public long estimateSize() { return Long.MAX_VALUE; }
+
         public int characteristics() {
             return Spliterator.ORDERED | Spliterator.NONNULL |
                 Spliterator.CONCURRENT;
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri Mar 01 16:23:31 2013 +0100
@@ -835,7 +835,7 @@
      * 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 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
      */
@@ -2777,7 +2777,7 @@
                 return (Spliterator<Map.Entry<K1,V1>>)
                     ((SubMap<K1,V1>)m).entryIterator();
         }
-        
+
         public Stream<Map.Entry<K1,V1>> stream() {
             return Streams.stream(spliterator());
         }
@@ -3623,8 +3623,8 @@
      * 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 use (1 << 2*levels) as a rough overestimate that
-     * minimizes risk of prematurely zeroing out while splitting.
+     * don't. But we can just use Integer.MAX_VALUE so that we
+     * don't prematurely zero out while splitting.
      */
     static class CSLMSpliterator<K,V> {
         final Comparator<? super K> comparator;
@@ -3634,24 +3634,20 @@
         int est;           // pseudo-size estimate
 
         CSLMSpliterator(ConcurrentSkipListMap<K,V> m) {
-            HeadIndex<K,V> h; Node<K,V> p; int d, n; Index<K,V> hd;
             this.comparator = m.comparator;
             this.fence = null;
-            for (;;) { // ensure h and n correspond to origin p
+            for (;;) { // ensure h corresponds to origin p
+                HeadIndex<K,V> h; Node<K,V> p;
                 Node<K,V> b = (h = m.head).node;
-                if ((p = b.next) == null) {
-                    n = 0;
-                    break;
-                }
-                if (p.value != null) {
-                    n = (d = h.level << 1) >= 31 ? Integer.MAX_VALUE : 1 << d;
+                if ((p = b.next) == null || p.value != null) {
+                    this.est = ((p == null) ? 0 :
+                                (p.next == null) ? 1 : Integer.MAX_VALUE);
+                    this.current = p;
+                    this.row = h;
                     break;
                 }
                 p.helpDelete(b, p.next);
             }
-            this.est = n;
-            this.current = p;
-            this.row = (h.right == null && (hd = h.down) != null) ? hd : h;
         }
 
         CSLMSpliterator(Comparator<? super K> comparator, Index<K,V> row,
@@ -3698,7 +3694,7 @@
         }
 
         @SuppressWarnings("unchecked")
-        public KeySpliterator<K,V> trySplit() {
+        public Spliterator<K> trySplit() {
             Node<K,V> e;
             Comparator<? super K> cmp = comparator;
             K f = fence;
@@ -3768,8 +3764,8 @@
         }
 
         public int characteristics() {
-            return  Spliterator.DISTINCT | Spliterator.SORTED | 
-                Spliterator.ORDERED | Spliterator.CONCURRENT | 
+            return Spliterator.DISTINCT | Spliterator.SORTED |
+                Spliterator.ORDERED | Spliterator.CONCURRENT |
                 Spliterator.NONNULL;
         }
 
@@ -3787,7 +3783,7 @@
         }
 
         @SuppressWarnings("unchecked")
-        public ValueSpliterator<K,V> trySplit() {
+        public Spliterator<V> trySplit() {
             Node<K,V> e;
             Comparator<? super K> cmp = comparator;
             K f = fence;
@@ -3874,7 +3870,7 @@
         }
 
         @SuppressWarnings("unchecked")
-        public EntrySpliterator<K,V> trySplit() {
+        public Spliterator<Map.Entry<K,V>> trySplit() {
             Node<K,V> e;
             Comparator<? super K> cmp = comparator;
             K f = fence;
@@ -3951,8 +3947,8 @@
         }
 
         public int characteristics() {
-            return  Spliterator.DISTINCT | Spliterator.SORTED | 
-                Spliterator.ORDERED | Spliterator.CONCURRENT | 
+            return Spliterator.DISTINCT | Spliterator.SORTED |
+                Spliterator.ORDERED | Spliterator.CONCURRENT |
                 Spliterator.NONNULL;
         }
     }
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Fri Mar 01 16:23:31 2013 +0100
@@ -493,7 +493,7 @@
     public Stream<E> stream() {
         return Streams.stream(spliterator());
     }
-    
+
     public Stream<E> parallelStream() {
         return Streams.parallelStream(spliterator());
     }
--- a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Mar 01 16:23:31 2013 +0100
@@ -1017,18 +1017,22 @@
     }
 
     Spliterator<E> spliterator() {
-        return Spliterators.spliterator(getArray(),
-                                        Spliterator.IMMUTABLE | Spliterator.ORDERED);
+        return Spliterators.spliterator
+            (getArray(), Spliterator.IMMUTABLE | Spliterator.ORDERED);
     }
 
     public Stream<E> stream() {
-        return Streams.stream(() -> spliterator(),
-                              Spliterator.SIZED | Spliterator.IMMUTABLE | Spliterator.ORDERED);
+        return Streams.stream(
+            () -> spliterator(),
+            Spliterator.SIZED | Spliterator.SUBSIZED |
+            Spliterator.IMMUTABLE | Spliterator.ORDERED);
     }
 
     public Stream<E> parallelStream() {
-        return Streams.parallelStream(() -> spliterator(),
-                                      Spliterator.SIZED | Spliterator.IMMUTABLE | Spliterator.ORDERED);
+        return Streams.parallelStream(
+            () -> spliterator(),
+            Spliterator.SIZED | Spliterator.SUBSIZED |
+            Spliterator.IMMUTABLE | Spliterator.ORDERED);
     }
 
     static final class COWIterator<E> implements ListIterator<E> {
@@ -1311,7 +1315,7 @@
             if (lo < 0 || hi > a.length)
                 throw new IndexOutOfBoundsException();
             return Spliterators.spliterator
-                    (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
+                (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
         }
 
         public Stream<E> stream() {
--- a/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java	Fri Mar 01 16:23:31 2013 +0100
@@ -38,9 +38,9 @@
 import java.util.Set;
 import java.util.AbstractSet;
 import java.util.Iterator;
-import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.stream.Streams;
 
 /**
@@ -283,7 +283,10 @@
      * @see #add(Object)
      */
     public boolean addAll(Collection<? extends E> c) {
-        return al.addAllAbsent(c) > 0;
+        if (c instanceof Set)
+            return al.addAll(c);
+        else
+            return al.addAllAbsent(c) > 0;
     }
 
     /**
@@ -390,20 +393,23 @@
     }
 
     Spliterator<E> spliterator() {
-        return Spliterators.spliterator(al.getArray(),
-                                        Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.ORDERED);
+        return Spliterators.spliterator
+            (al.getArray(), Spliterator.IMMUTABLE |
+             Spliterator.DISTINCT | Spliterator.ORDERED);
     }
 
     public Stream<E> stream() {
-        return Streams.stream(() -> spliterator(),
-                              Spliterator.SIZED | Spliterator.SUBSIZED |
-                              Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.ORDERED);
+        return Streams.stream(
+            () -> spliterator(),
+            Spliterator.SIZED | Spliterator.SUBSIZED |
+            Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.ORDERED);
     }
 
     public Stream<E> parallelStream() {
-        return Streams.parallelStream(() -> spliterator(),
-                                      Spliterator.SIZED | Spliterator.SUBSIZED |
-                                      Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.ORDERED);
+        return Streams.parallelStream(
+            () -> spliterator(),
+            Spliterator.SIZED | Spliterator.SUBSIZED |
+            Spliterator.IMMUTABLE | Spliterator.DISTINCT | Spliterator.ORDERED);
     }
 
     /**
--- a/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Fri Mar 01 16:23:31 2013 +0100
@@ -39,10 +39,10 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
 import java.util.function.Consumer;
@@ -1148,21 +1148,6 @@
     private class Itr extends AbstractItr {
         Node<E> firstNode() { return first; }
         Node<E> nextNode(Node<E> n) { return n.next; }
-        // minimal, unsplittable Spliterator implementation
-        public boolean tryAdvance(Consumer<? super E> action) {
-            if (hasNext()) {
-                action.accept(next());
-                return true;
-            }
-            return false;
-        }
-        public void forEach(Consumer<? super E> action) {
-            while (hasNext())
-                action.accept(next());
-        }
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.CONCURRENT;
-        }
     }
 
     /** Descending iterator */
@@ -1179,7 +1164,7 @@
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
         long est;           // size estimate
-        LBDSpliterator(LinkedBlockingDeque<E> queue) { 
+        LBDSpliterator(LinkedBlockingDeque<E> queue) {
             this.queue = queue;
             this.est = queue.size();
         }
@@ -1212,8 +1197,8 @@
                 else if ((est -= i) <= 0L)
                     est = 1L;
                 return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                                  Spliterator.CONCURRENT);
+                    (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                     Spliterator.CONCURRENT);
             }
             return null;
         }
--- a/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Fri Mar 01 16:23:31 2013 +0100
@@ -35,7 +35,6 @@
 
 package java.util.concurrent;
 
-import java.util.Spliterators;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
@@ -44,6 +43,7 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
 import java.util.function.Consumer;
@@ -901,8 +901,8 @@
                 else if ((est -= i) <= 0L)
                     est = 1L;
                 return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                                  Spliterator.CONCURRENT);
+                    (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                     Spliterator.CONCURRENT);
             }
             return null;
         }
--- a/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Fri Mar 01 16:23:31 2013 +0100
@@ -40,9 +40,9 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
-import java.util.Spliterators;
 import java.util.concurrent.locks.LockSupport;
 import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
 import java.util.function.Consumer;
@@ -931,7 +931,7 @@
                 unsplice(lastPred, lastRet);
         }
     }
-    
+
     // Very similar to ConcurrentLinkedQueue spliterator
     static final class LTQSpliterator<E> implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 10;  // saturate batch size
@@ -939,12 +939,12 @@
         Node current;    // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
-        LTQSpliterator(LinkedTransferQueue<E> queue) { 
+        LTQSpliterator(LinkedTransferQueue<E> queue) {
             this.queue = queue;
         }
 
-        /*
-         * Split into arrays of arithmetically increasing batch sizes,
+        /**
+         * Splits into arrays of arithmetically increasing batch sizes,
          * giving up at MAX_BATCH.  Treat the result as a
          * CopyOnWriteArrayList array snapshot.  This will only
          * improve parallel performance if per-element forEach actions
@@ -955,20 +955,21 @@
             Node p; int n;
             final LinkedTransferQueue<E> q = this.queue;
             if (!exhausted && (n = batch + 1) > 0 && n <= MAX_BATCH &&
-                ((p = current) != null || (p = q.firstDataNode()) != null)) {
+                ((p = current) != null || (p = q.firstDataNode()) != null) &&
+                p.next != null) {
                 Object[] a = new Object[batch = n];
                 int i = 0;
                 do {
                     if ((a[i] = p.item) != null)
                         ++i;
-                    if (p == (p = p.next)) 
+                    if (p == (p = p.next))
                         p = q.firstDataNode();
                 } while (p != null && i < n);
                 if ((current = p) == null)
                     exhausted = true;
                 return Spliterators.spliterator
-                        (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
-                                  Spliterator.CONCURRENT);
+                    (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
+                     Spliterator.CONCURRENT);
             }
             return null;
         }
@@ -983,7 +984,7 @@
                 exhausted = true;
                 do {
                     Object e = p.item;
-                    if (p == (p = p.next)) 
+                    if (p == (p = p.next))
                         p = q.firstDataNode();
                     if (e != null)
                         action.accept((E)e);
@@ -1001,7 +1002,7 @@
                 Object e;
                 do {
                     e = p.item;
-                    if (p == (p = p.next)) 
+                    if (p == (p = p.next))
                         p = q.firstDataNode();
                 } while (e == null && p != null);
                 if ((current = p) == null)
@@ -1014,6 +1015,8 @@
             return false;
         }
 
+        public long estimateSize() { return Long.MAX_VALUE; }
+
         public int characteristics() {
             return Spliterator.ORDERED | Spliterator.NONNULL |
                 Spliterator.CONCURRENT;
--- a/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Fri Mar 01 16:23:31 2013 +0100
@@ -35,7 +35,6 @@
 
 package java.util.concurrent;
 
-import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.AbstractQueue;
@@ -48,9 +47,9 @@
 import java.util.Queue;
 import java.util.SortedSet;
 import java.util.Spliterator;
-import java.util.function.Consumer;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
+import java.util.function.Consumer;
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} that uses
--- a/src/share/classes/java/util/concurrent/SynchronousQueue.java	Fri Mar 01 11:33:02 2013 +0100
+++ b/src/share/classes/java/util/concurrent/SynchronousQueue.java	Fri Mar 01 16:23:31 2013 +0100
@@ -39,9 +39,9 @@
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.*;
 import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
-import java.util.function.Consumer;
 
 /**
  * A {@linkplain BlockingQueue blocking queue} in which each insert
@@ -66,7 +66,7 @@
  * 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 {@code true} grants threads access in FIFO order.