Mercurial > hg > openjdk > lambda > jdk
changeset 7552:996188a59559
Updates to spliterators.
Contributed-by: Doug Lea <dl@cs.oswego.edu>
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.