changeset 7688:d6e3a0014aba

Merge
author mduigou
date Mon, 18 Mar 2013 22:09:50 -0700
parents 6361a87448c2 ddd9febad832
children 04a196355eb0
files
diffstat 42 files changed, 1754 insertions(+), 777 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/Arrays.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/Arrays.java	Mon Mar 18 22:09:50 2013 -0700
@@ -30,6 +30,10 @@
 import java.util.function.BinaryOperator;
 import java.util.function.DoubleBinaryOperator;
 import java.util.function.IntBinaryOperator;
+import java.util.function.IntFunction;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
+import java.util.function.IntUnaryOperator;
 import java.util.function.LongBinaryOperator;
 import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
@@ -4430,6 +4434,108 @@
     }
 
     /**
+     * Initializes all elements of the specified array, using the provided
+     * generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     * @param <T> Type of elements of the array
+     */
+    public<T> void setAll(T[] array, IntFunction<? extends T> generator) {
+        for (int i=0; i<array.length; i++)
+            array[i] = generator.apply(i);
+    }
+
+    /**
+     * Initializes all elements of the specified array, in parallel, using the
+     * provided generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     * @param <T> Type of elements of the array
+     */
+    public<T> void parallelSetAll(T[] array, IntFunction<? extends T> generator) {
+        Streams.intRange(0, array.length).parallel().forEach(i -> { array[i] = generator.apply(i); });
+    }
+
+    /**
+     * Initialize all elements of the specified array, using the provided
+     * generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     */
+    public void setAll(int[] array, IntUnaryOperator generator) {
+        for (int i=0; i<array.length; i++)
+            array[i] = generator.applyAsInt(i);
+    }
+
+    /**
+     * Initialize all elements of the specified array, in parallel, using the
+     * provided generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     * value for that position
+     */
+    public<T> void parallelSetAll(int[] array, IntUnaryOperator generator) {
+        Streams.intRange(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsInt(i); });
+    }
+
+    /**
+     * Initialize all elements of the specified array, using the provided
+     * generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     */
+    public void setAll(long[] array, IntToLongFunction generator) {
+        for (int i=0; i<array.length; i++)
+            array[i] = generator.applyAsLong(i);
+    }
+
+    /**
+     * Initialize all elements of the specified array, in parallel, using the
+     * provided generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     */
+    public<T> void parallelSetAll(long[] array, IntToLongFunction generator) {
+        Streams.intRange(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsLong(i); });
+    }
+
+    /**
+     * Initialize all elements of the specified array, using the provided
+     * generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     */
+    public void setAll(double[] array, IntToDoubleFunction generator) {
+        for (int i=0; i<array.length; i++)
+            array[i] = generator.applyAsDouble(i);
+    }
+
+    /**
+     * Initialize all elements of the specified array, in parallel, using the
+     * provided generator function to compute each element.
+     *
+     * @param array Array to be initialized
+     * @param generator Function accepting an index and producing the desired
+     *        value for that position
+     */
+    public<T> void parallelSetAll(double[] array, IntToDoubleFunction generator) {
+        Streams.intRange(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsDouble(i); });
+    }
+
+    /**
      * Checks that {@code fromIndex} and {@code toIndex} are in
      * the range and throws an exception if they aren't.
      */
--- a/src/share/classes/java/util/HashMap.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/HashMap.java	Mon Mar 18 22:09:50 2013 -0700
@@ -27,6 +27,8 @@
 
 import java.io.*;
 import java.util.function.Consumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
 
 /**
  * Hash table based implementation of the <tt>Map</tt> interface.  This
@@ -352,6 +354,13 @@
         return null == entry ? null : entry.getValue();
     }
 
+    @Override
+    public V getOrDefault(Object key, V defaultValue) {
+        Entry<K,V> entry = getEntry(key);
+
+        return null == entry ? defaultValue : entry.getValue();
+    }
+
     /**
      * Returns <tt>true</tt> if this map contains a mapping for the
      * specified key.
@@ -569,6 +578,235 @@
         return (e == null ? null : e.value);
     }
 
+    // optimized implementations of default methods in Map
+
+    @Override
+    public V putIfAbsent(K key, V value) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> e = (Entry<K,V>)table[i];
+        for(; e != null; e = e.next) {
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                return e.value;
+            }
+        }
+
+        modCount++;
+        addEntry(hash, key, value, i);
+        return null;
+    }
+
+    @Override
+    public boolean remove(Object key, Object value) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> prev = (Entry<K,V>)table[i];
+        Entry<K,V> e = prev;
+
+        while (e != null) {
+            Entry<K,V> next = e.next;
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                modCount++;
+                size--;
+                if (prev == e)
+                    table[i] = next;
+                else
+                    prev.next = next;
+                e.recordRemoval(this);
+                return true;
+            }
+            prev = e;
+            e = next;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean replace(K key, V oldValue, V newValue) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> e = (Entry<K,V>)table[i];
+        for(; e != null; e = e.next) {
+            if (e.hash == hash && Objects.equals(e.key, key) && Objects.equals(e.value, oldValue)) {
+                e.value = newValue;
+                e.recordAccess(this);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public V replace(K key, V value) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> e = (Entry<K,V>)table[i];
+        for(; e != null; e = e.next) {
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                V oldValue = e.value;
+                e.value = value;
+                e.recordAccess(this);
+                return oldValue;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> e = (Entry<K,V>)table[i];
+        for(; e != null; e = e.next) {
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                V oldValue = e.value;
+                return oldValue == null ? mappingFunction.apply(key) : oldValue;
+            }
+        }
+
+        V newValue = mappingFunction.apply(key);
+        if (newValue != null) {
+            modCount++;
+            addEntry(hash, key, newValue, i);
+        }
+
+        return newValue;
+    }
+
+    @Override
+    public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> prev = (Entry<K,V>)table[i];
+        Entry<K,V> e = prev;
+
+        while (e != null) {
+            Entry<K,V> next = e.next;
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                V oldValue = e.value;
+                if (oldValue == null)
+                    break;
+                V newValue = remappingFunction.apply(key, oldValue);
+                modCount++;
+                if (newValue == null) {
+                    size--;
+                    if (prev == e)
+                        table[i] = next;
+                    else
+                        prev.next = next;
+                    e.recordRemoval(this);
+                }
+                else {
+                    e.value = newValue;
+                    e.recordAccess(this);
+                }
+                return newValue;
+            }
+            prev = e;
+            e = next;
+        }
+
+        return null;
+    }
+
+    @Override
+    public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> prev = (Entry<K,V>)table[i];
+        Entry<K,V> e = prev;
+
+        while (e != null) {
+            Entry<K,V> next = e.next;
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                V oldValue = e.value;
+                V newValue = remappingFunction.apply(key, oldValue);
+                if (oldValue != null) {
+                    modCount++;
+                    if (newValue == null) {
+                        size--;
+                        if (prev == e)
+                            table[i] = next;
+                        else
+                            prev.next = next;
+                        e.recordRemoval(this);
+                    }
+                    else {
+                        e.value = newValue;
+                        e.recordAccess(this);
+                    }
+                }
+                return newValue;
+            }
+            prev = e;
+            e = next;
+        }
+
+        V newValue = remappingFunction.apply(key, null);
+        if (newValue != null) {
+            modCount++;
+            addEntry(hash, key, newValue, i);
+        }
+
+        return newValue;
+    }
+
+    @Override
+    public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+        int hash = (key == null) ? 0 : hash(key);
+        int i = indexFor(hash, table.length);
+        @SuppressWarnings("unchecked")
+        Entry<K,V> prev = (Entry<K,V>)table[i];
+        Entry<K,V> e = prev;
+
+        while (e != null) {
+            Entry<K,V> next = e.next;
+            if (e.hash == hash && Objects.equals(e.key, key)) {
+                V oldValue = e.value;
+                if (oldValue != null) {
+                    V newValue = remappingFunction.apply(oldValue, value);
+                    modCount++;
+                    if (newValue == null) {
+                        size--;
+                        if (prev == e)
+                            table[i] = next;
+                        else
+                            prev.next = next;
+                        e.recordRemoval(this);
+                    }
+                    else {
+                        e.value = newValue;
+                        e.recordAccess(this);
+                    }
+                    return newValue;
+                }
+                else
+                    return value;
+            }
+            prev = e;
+            e = next;
+        }
+
+        if (value != null) {
+            modCount++;
+            addEntry(hash, key, value, i);
+        }
+
+        return value;
+    }
+
+    // end of optimized implementations of default methods in Map
+
     /**
      * Removes and returns the entry associated with the specified key
      * in the HashMap.  Returns null if the HashMap contains no mapping
--- a/src/share/classes/java/util/Map.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/Map.java	Mon Mar 18 22:09:50 2013 -0700
@@ -483,6 +483,28 @@
     // Defaultable methods
 
     /**
+    *  Returns the value to which the specified key is mapped,
+    *  or {@code defaultValue} if this map contains no mapping
+    *  for the key.
+    *
+    * @param key the key whose associated value is to be returned
+    * @return the value to which the specified key is mapped, or
+    * {@code defaultValue} if this map contains no mapping for the key
+    * @throws ClassCastException if the key is of an inappropriate type for
+    * this map
+    * (<a href="Collection.html#optional-restrictions">optional</a>)
+    * @throws NullPointerException if the specified key is null and this map
+    * does not permit null keys
+    * (<a href="Collection.html#optional-restrictions">optional</a>)
+    */
+    default V getOrDefault(Object key, V defaultValue) {
+        V v;
+        return (null != (v = get(key)))
+            ? v
+            : containsKey(key) ? null : defaultValue;
+    }
+
+    /**
      * Performs the given action on each entry in this map, in the
      * order entries are returned by an entry set iterator, until all entries
      * have been processed or the action throws an {@code Exception}.
@@ -619,7 +641,7 @@
      * The default implementation is equivalent to, for this {@code map}:
      *
      * <pre> {@code
-     * if (map.containsKey(key) && map.get(key).equals(value)) {
+     * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
      *   map.remove(key);
      *   return true;
      * } else
@@ -639,7 +661,7 @@
      * @since 1.8
      */
     default boolean remove(Object key, Object value) {
-        if (!containsKey(key) || !get(key).equals(value))
+        if (!containsKey(key) || !Objects.equals(get(key), value))
             return false;
         remove(key);
         return true;
@@ -660,7 +682,7 @@
      * The default implementation is equivalent to, for this {@code map}:
      *
      * <pre> {@code
-     * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
+     * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
      *   map.put(key, newValue);
      *   return true;
      * } else
@@ -681,7 +703,7 @@
      * @since 1.8
      */
     default boolean replace(K key, V oldValue, V newValue) {
-        if (!containsKey(key) || !get(key).equals(oldValue))
+        if (!containsKey(key) || !Objects.equals(get(key), oldValue))
             return false;
         put(key, newValue);
         return true;
@@ -908,15 +930,27 @@
      */
     default V compute(K key,
                       BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+        V oldValue = get(key);
         for (;;) {
-            V oldValue = get(key);
             V newValue = remappingFunction.apply(key, oldValue);
-            if (newValue != null) {
-                if (replace(key, oldValue, newValue))
-                    return newValue;
+            if (oldValue != null) {
+                if (newValue != null) {
+                    if (replace(key, oldValue, newValue))
+                        return newValue;
+                }
+                else if (remove(key, oldValue)) {
+                    return null;
+                }
+                oldValue = get(key);
             }
-            else if (remove(key, oldValue))
-                return null;
+            else {
+                if (newValue != null) {
+                    if ((oldValue = putIfAbsent(key, newValue)) == null)
+                        return newValue;
+                }
+                else
+                    return null;
+            }
         }
     }
 
@@ -978,18 +1012,27 @@
      */
     default V merge(K key, V value,
                     BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+        V oldValue = get(key);
         for (;;) {
-            V oldValue, newValue;
-            if ((oldValue = get(key)) == null) {
-                if (value == null || putIfAbsent(key, value) == null)
-                    return value;
+            if (oldValue != null) {
+                V newValue = remappingFunction.apply(oldValue, value);
+                if (newValue != null) {
+                    if (replace(key, oldValue, newValue))
+                        return newValue;
+                }
+                else if (remove(key, oldValue)) {
+                    return null;
+                }
+                oldValue = get(key);
             }
-            else if ((newValue = remappingFunction.apply(oldValue, value)) != null) {
-                if (replace(key, oldValue, newValue))
-                    return newValue;
+            else {
+                if (value != null) {
+                    if ((oldValue = putIfAbsent(key, value)) == null)
+                        return value;
+                }
+                else
+                    return null;
             }
-            else if (remove(key, oldValue))
-                return null;
         }
     }
 }
--- a/src/share/classes/java/util/concurrent/CompletableFuture.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/CompletableFuture.java	Mon Mar 18 22:09:50 2013 -0700
@@ -62,19 +62,32 @@
  * {@link #cancel cancel}
  * a CompletableFuture, only one of them succeeds.
  *
- * <p>Methods are available for adding dependents based on Functions,
- * Consumers, and Runnables. The appropriate form to use depends on
- * whether actions require arguments and/or produce results. Actions
- * may also be triggered after either or both the current and another
+ * <p>Methods are available for adding dependents based on
+ * user-provided Functions, Consumers, or Runnables. The appropriate
+ * form to use depends on whether actions require arguments and/or
+ * produce results.  Completion of a dependent action will trigger the
+ * completion of another CompletableFuture.  Actions may also be
+ * triggered after either or both the current and another
  * CompletableFuture complete.  Multiple CompletableFutures may also
  * be grouped as one using {@link #anyOf(CompletableFuture...)} and
  * {@link #allOf(CompletableFuture...)}.
  *
- * <p>Actions supplied for dependent completions (mainly using methods
- * with prefix {@code then}) may be performed by the thread that
- * completes the current CompletableFuture, or by any other caller of
- * these methods.  There are no guarantees about the order of
- * processing completions unless constrained by these methods.
+ * <p>CompletableFutures themselves do not execute asynchronously.
+ * However, actions supplied for dependent completions of another
+ * CompletableFuture may do so, depending on whether they are provided
+ * via one of the <em>async</em> methods (that is, methods with names
+ * of the form <tt><var>xxx</var>Async</tt>).  The <em>async</em>
+ * methods provide a way to commence asynchronous processing of an
+ * action using either a given {@link Executor} or by default the
+ * {@link ForkJoinPool#commonPool()}. To simplify monitoring,
+ * debugging, and tracking, all generated asynchronous tasks are
+ * instances of the marker interface {@link AsynchronousCompletionTask}.
+ *
+ * <p>Actions supplied for dependent completions of <em>non-async</em>
+ * methods may be performed by the thread that completes the current
+ * CompletableFuture, or by any other caller of these methods.  There
+ * are no guarantees about the order of processing completions unless
+ * constrained by these methods.
  *
  * <p>Since (unlike {@link FutureTask}) this class has no direct
  * control over the computation that causes it to be completed,
@@ -99,15 +112,6 @@
  * methods {@link #join()} and {@link #getNow} throw the
  * CompletionException, which simplifies usage.
  *
- * <p>CompletableFutures themselves do not execute asynchronously.
- * However, the {@code async} methods provide commonly useful ways to
- * commence asynchronous processing, using either a given {@link
- * Executor} or by default the {@link ForkJoinPool#commonPool()}, of a
- * function or action that will result in the completion of a new
- * CompletableFuture. To simplify monitoring, debugging, and tracking,
- * all generated asynchronous tasks are instances of the tagging
- * interface {@link AsynchronousCompletionTask}.
- *
  * @author Doug Lea
  * @since 1.8
  */
@@ -413,9 +417,11 @@
     /* ------------- Async tasks -------------- */
 
     /**
-     * A tagging interface identifying asynchronous tasks produced by
+     * A marker interface identifying asynchronous tasks produced by
      * {@code async} methods. This may be useful for monitoring,
      * debugging, and tracking asynchronous activities.
+     *
+     * @since 1.8
      */
     public static interface AsynchronousCompletionTask {
     }
@@ -474,8 +480,8 @@
     }
 
     static final class AsyncApply<T,U> extends Async {
+        final T arg;
         final Function<? super T,? extends U> fn;
-        final T arg;
         final CompletableFuture<U> dst;
         AsyncApply(T arg, Function<? super T,? extends U> fn,
                    CompletableFuture<U> dst) {
@@ -499,9 +505,9 @@
     }
 
     static final class AsyncBiApply<T,U,V> extends Async {
-        final BiFunction<? super T,? super U,? extends V> fn;
         final T arg1;
         final U arg2;
+        final BiFunction<? super T,? super U,? extends V> fn;
         final CompletableFuture<V> dst;
         AsyncBiApply(T arg1, U arg2,
                      BiFunction<? super T,? super U,? extends V> fn,
@@ -526,8 +532,8 @@
     }
 
     static final class AsyncAccept<T> extends Async {
+        final T arg;
         final Consumer<? super T> fn;
-        final T arg;
         final CompletableFuture<Void> dst;
         AsyncAccept(T arg, Consumer<? super T> fn,
                     CompletableFuture<Void> dst) {
@@ -550,9 +556,9 @@
     }
 
     static final class AsyncBiAccept<T,U> extends Async {
-        final BiConsumer<? super T,? super U> fn;
         final T arg1;
         final U arg2;
+        final BiConsumer<? super T,? super U> fn;
         final CompletableFuture<Void> dst;
         AsyncBiAccept(T arg1, U arg2,
                       BiConsumer<? super T,? super U> fn,
@@ -576,8 +582,8 @@
     }
 
     static final class AsyncCompose<T,U> extends Async {
+        final T arg;
         final Function<? super T, CompletableFuture<U>> fn;
-        final T arg;
         final CompletableFuture<U> dst;
         AsyncCompose(T arg,
                      Function<? super T, CompletableFuture<U>> fn,
@@ -589,19 +595,17 @@
             if ((d = this.dst) != null && d.result == null) {
                 try {
                     fr = fn.apply(arg);
-                    ex = null;
+                    ex = (fr == null) ? new NullPointerException() : null;
                 } catch (Throwable rex) {
                     ex = rex;
                     fr = null;
                 }
                 if (ex != null)
                     u = null;
-                else if (fr == null) {
-                    ex = new NullPointerException();
-                    u = null;
-                }
                 else {
                     Object r = fr.result;
+                    if (r == null)
+                        r = fr.waitingGet(false);
                     if (r instanceof AltResult) {
                         ex = ((AltResult)r).ex;
                         u = null;
@@ -1245,7 +1249,7 @@
         final CompletableFuture<U> dst;
         HandleCompletion(CompletableFuture<? extends T> src,
                          BiFunction<? super T, Throwable, ? extends U> fn,
-                         final CompletableFuture<U> dst) {
+                         CompletableFuture<U> dst) {
             this.src = src; this.fn = fn; this.dst = dst;
         }
         public final void run() {
@@ -1286,7 +1290,7 @@
         final Executor executor;
         ComposeCompletion(CompletableFuture<? extends T> src,
                           Function<? super T, CompletableFuture<U>> fn,
-                          final CompletableFuture<U> dst, Executor executor) {
+                          CompletableFuture<U> dst, Executor executor) {
             this.src = src; this.fn = fn; this.dst = dst;
             this.executor = executor;
         }
@@ -1366,13 +1370,13 @@
     }
 
     /**
-     * Asynchronously executes in the {@link
-     * ForkJoinPool#commonPool()}, a task that completes the returned
-     * CompletableFuture with the result of the given Supplier.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * by a task running in the {@link ForkJoinPool#commonPool()} with
+     * the value obtained by calling the given Supplier.
      *
      * @param supplier a function returning the value to be used
      * to complete the returned CompletableFuture
-     * @return the CompletableFuture
+     * @return the new CompletableFuture
      */
     public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
         if (supplier == null) throw new NullPointerException();
@@ -1383,14 +1387,14 @@
     }
 
     /**
-     * Asynchronously executes using the given executor, a task that
-     * completes the returned CompletableFuture with the result of the
-     * given Supplier.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * by a task running in the given executor with the value obtained
+     * by calling the given Supplier.
      *
      * @param supplier a function returning the value to be used
      * to complete the returned CompletableFuture
      * @param executor the executor to use for asynchronous execution
-     * @return the CompletableFuture
+     * @return the new CompletableFuture
      */
     public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                        Executor executor) {
@@ -1402,13 +1406,13 @@
     }
 
     /**
-     * Asynchronously executes in the {@link
-     * ForkJoinPool#commonPool()} a task that runs the given action,
-     * and then completes the returned CompletableFuture.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * by a task running in the {@link ForkJoinPool#commonPool()} after
+     * it runs the given action.
      *
      * @param runnable the action to run before completing the
      * returned CompletableFuture
-     * @return the CompletableFuture
+     * @return the new CompletableFuture
      */
     public static CompletableFuture<Void> runAsync(Runnable runnable) {
         if (runnable == null) throw new NullPointerException();
@@ -1419,14 +1423,14 @@
     }
 
     /**
-     * Asynchronously executes using the given executor, a task that
-     * runs the given action, and then completes the returned
-     * CompletableFuture.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * by a task running in the given executor after it runs the given
+     * action.
      *
      * @param runnable the action to run before completing the
      * returned CompletableFuture
      * @param executor the executor to use for asynchronous execution
-     * @return the CompletableFuture
+     * @return the new CompletableFuture
      */
     public static CompletableFuture<Void> runAsync(Runnable runnable,
                                                    Executor executor) {
@@ -1601,12 +1605,13 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed with
-     * the result of the given function of this CompletableFuture.
-     * If this CompletableFuture completes exceptionally,
-     * then the returned CompletableFuture also does so,
-     * with a CompletionException holding this exception as
-     * its cause.
+     * Returns a new CompletableFuture that is completed
+     * when this CompletableFuture completes, with the result of the
+     * given function of this CompletableFuture's result.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding this exception as its cause.
      *
      * @param fn the function to use to compute the value of
      * the returned CompletableFuture
@@ -1617,11 +1622,13 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the {@link ForkJoinPool#commonPool()} with the
-     * result of the given function of this CompletableFuture.  If
-     * this CompletableFuture completes exceptionally, then the
-     * returned CompletableFuture also does so, with a
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when this CompletableFuture completes, with the result of the
+     * given function of this CompletableFuture's result, called from a
+     * task running in the {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
      * CompletionException holding this exception as its cause.
      *
      * @param fn the function to use to compute the value of
@@ -1634,12 +1641,14 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the given executor with the result of the given
-     * function of this CompletableFuture.  If this CompletableFuture
-     * completes exceptionally, then the returned CompletableFuture
-     * also does so, with a CompletionException holding this exception as
-     * its cause.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when this CompletableFuture completes, with the result of the
+     * given function of this CompletableFuture's result, called from a
+     * task running in the given executor.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding this exception as its cause.
      *
      * @param fn the function to use to compute the value of
      * the returned CompletableFuture
@@ -1699,12 +1708,13 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed after
-     * performing the given action with this CompletableFuture's
-     * result when it completes.  If this CompletableFuture
-     * completes exceptionally, then the returned CompletableFuture
-     * also does so, with a CompletionException holding this exception as
-     * its cause.
+     * Returns a new CompletableFuture that is completed
+     * when this CompletableFuture completes, after performing the given
+     * action with this CompletableFuture's result.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding this exception as its cause.
      *
      * @param block the action to perform before completing the
      * returned CompletableFuture
@@ -1715,12 +1725,14 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the {@link ForkJoinPool#commonPool()} with this
-     * CompletableFuture's result when it completes.  If this
-     * CompletableFuture completes exceptionally, then the returned
-     * CompletableFuture also does so, with a CompletionException holding
-     * this exception as its cause.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when this CompletableFuture completes, after performing the given
+     * action with this CompletableFuture's result from a task running
+     * in the {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding this exception as its cause.
      *
      * @param block the action to perform before completing the
      * returned CompletableFuture
@@ -1731,12 +1743,14 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the given executor with this
-     * CompletableFuture's result when it completes.  If this
-     * CompletableFuture completes exceptionally, then the returned
-     * CompletableFuture also does so, with a CompletionException holding
-     * this exception as its cause.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when this CompletableFuture completes, after performing the given
+     * action with this CompletableFuture's result from a task running
+     * in the given executor.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding this exception as its cause.
      *
      * @param block the action to perform before completing the
      * returned CompletableFuture
@@ -1793,9 +1807,11 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed after
-     * performing the given action when this CompletableFuture
-     * completes.  If this CompletableFuture completes exceptionally,
+     * Returns a new CompletableFuture that is completed
+     * when this CompletableFuture completes, after performing the given
+     * action.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding this exception as its cause.
      *
@@ -1808,10 +1824,11 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the {@link ForkJoinPool#commonPool()} after
-     * performing the given action when this CompletableFuture
-     * completes.  If this CompletableFuture completes exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when this CompletableFuture completes, after performing the given
+     * action from a task running in the {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding this exception as its cause.
      *
@@ -1824,12 +1841,13 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the given executor after performing the given
-     * action when this CompletableFuture completes.  If this
-     * CompletableFuture completes exceptionally, then the returned
-     * CompletableFuture also does so, with a CompletionException holding
-     * this exception as its cause.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when this CompletableFuture completes, after performing the given
+     * action from a task running in the given executor.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding this exception as its cause.
      *
      * @param action the action to perform before completing the
      * returned CompletableFuture
@@ -1881,11 +1899,13 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed with
-     * the result of the given function of this and the other given
-     * CompletableFuture's results when both complete.  If this or
-     * the other CompletableFuture complete exceptionally, then the
-     * returned CompletableFuture also does so, with a
+     * Returns a new CompletableFuture that is completed
+     * when both this and the other given CompletableFuture complete,
+     * with the result of the given function of the results of the two
+     * CompletableFutures.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
+     * then the returned CompletableFuture also does so, with a
      * CompletionException holding the exception as its cause.
      *
      * @param other the other CompletableFuture
@@ -1900,12 +1920,14 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is asynchronously
-     * completed using the {@link ForkJoinPool#commonPool()} with
-     * the result of the given function of this and the other given
-     * CompletableFuture's results when both complete.  If this or
-     * the other CompletableFuture complete exceptionally, then the
-     * returned CompletableFuture also does so, with a
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when both this and the other given CompletableFuture complete,
+     * with the result of the given function of the results of the two
+     * CompletableFutures, called from a task running in the
+     * {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
+     * then the returned CompletableFuture also does so, with a
      * CompletionException holding the exception as its cause.
      *
      * @param other the other CompletableFuture
@@ -1920,12 +1942,14 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is
-     * asynchronously completed using the given executor with the
-     * result of the given function of this and the other given
-     * CompletableFuture's results when both complete.  If this or
-     * the other CompletableFuture complete exceptionally, then the
-     * returned CompletableFuture also does so, with a
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when both this and the other given CompletableFuture complete,
+     * with the result of the given function of the results of the two
+     * CompletableFutures, called from a task running in the
+     * given executor.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
+     * then the returned CompletableFuture also does so, with a
      * CompletionException holding the exception as its cause.
      *
      * @param other the other CompletableFuture
@@ -2011,12 +2035,14 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed with
-     * the results of this and the other given CompletableFuture if
-     * both complete.  If this and/or the other CompletableFuture
-     * complete exceptionally, then the returned CompletableFuture
-     * also does so, with a CompletionException holding one of these
-     * exceptions as its cause.
+     * Returns a new CompletableFuture that is completed
+     * when both this and the other given CompletableFuture complete,
+     * after performing the given action with the results of the two
+     * CompletableFutures.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding one of these exceptions as its cause.
      *
      * @param other the other CompletableFuture
      * @param block the action to perform before completing the
@@ -2030,13 +2056,15 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the {@link ForkJoinPool#commonPool()} with
-     * the results of this and the other given CompletableFuture when
-     * both complete.  If this and/or the other CompletableFuture
-     * complete exceptionally, then the returned CompletableFuture
-     * also does so, with a CompletionException holding one of these
-     * exceptions as its cause.
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when both this and the other given CompletableFuture complete,
+     * after performing the given action with the results of the two
+     * CompletableFutures from a task running in the {@link
+     * ForkJoinPool#commonPool()}.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
+     * then the returned CompletableFuture also does so, with a
+     * CompletionException holding one of these exceptions as its cause.
      *
      * @param other the other CompletableFuture
      * @param block the action to perform before completing the
@@ -2050,10 +2078,12 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the given executor with the results of
-     * this and the other given CompletableFuture when both complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when both this and the other given CompletableFuture complete,
+     * after performing the given action with the results of the two
+     * CompletableFutures from a task running in the given executor.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding one of these exceptions as its cause.
      *
@@ -2139,9 +2169,11 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed when
-     * this and the other given CompletableFuture both complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is completed
+     * when both this and the other given CompletableFuture complete,
+     * after performing the given action.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding one of these exceptions as its cause.
      *
@@ -2156,10 +2188,12 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the {@link ForkJoinPool#commonPool()}
-     * when this and the other given CompletableFuture both complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when both this and the other given CompletableFuture complete,
+     * after performing the given action from a task running in the
+     * {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding one of these exceptions as its cause.
      *
@@ -2174,10 +2208,12 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the given executor when this and the
-     * other given CompletableFuture both complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when both this and the other given CompletableFuture complete,
+     * after performing the given action from a task running in the
+     * given executor.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding one of these exceptions as its cause.
      *
@@ -2248,14 +2284,16 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed with
-     * the result of the given function of either this or the other
-     * given CompletableFuture's results when either complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is completed
+     * when either this or the other given CompletableFuture completes,
+     * with the result of the given function of either this or the other
+     * CompletableFuture's result.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which result or exception is used
-     * in the returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param fn the function to use to compute the value of
@@ -2269,15 +2307,17 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the {@link ForkJoinPool#commonPool()} with
-     * the result of the given function of either this or the other
-     * given CompletableFuture's results when either complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when either this or the other given CompletableFuture completes,
+     * with the result of the given function of either this or the other
+     * CompletableFuture's result, called from a task running in the
+     * {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which result or exception is used
-     * in the returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param fn the function to use to compute the value of
@@ -2291,15 +2331,17 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the given executor with the result of the
-     * given function of either this or the other given
-     * CompletableFuture's results when either complete.  If this
-     * and/or the other CompletableFuture complete exceptionally, then
-     * the returned CompletableFuture may also do so, with a
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when either this or the other given CompletableFuture completes,
+     * with the result of the given function of either this or the other
+     * CompletableFuture's result, called from a task running in the
+     * given executor.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
+     * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which result or exception is used
-     * in the returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param fn the function to use to compute the value of
@@ -2368,14 +2410,16 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed after
-     * performing the given action with the result of either this or the
-     * other given CompletableFuture's result, when either complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is completed
+     * when either this or the other given CompletableFuture completes,
+     * after performing the given action with the result of either this
+     * or the other CompletableFuture's result.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which exception is used in the
-     * returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param block the action to perform before completing the
@@ -2389,15 +2433,17 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the {@link ForkJoinPool#commonPool()},
-     * performing the given action with the result of either this or
-     * the other given CompletableFuture's result, when either complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when either this or the other given CompletableFuture completes,
+     * after performing the given action with the result of either this
+     * or the other CompletableFuture's result from a task running in
+     * the {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which exception is used in the
-     * returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param block the action to perform before completing the
@@ -2411,15 +2457,17 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the given executor, performing the given
-     * action with the result of either this or the other given
-     * CompletableFuture's result, when either complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when either this or the other given CompletableFuture completes,
+     * after performing the given action with the result of either this
+     * or the other CompletableFuture's result from a task running in
+     * the given executor.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which exception is used in the
-     * returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param block the action to perform before completing the
@@ -2487,13 +2535,15 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * after this or the other given CompletableFuture complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is completed
+     * when either this or the other given CompletableFuture completes,
+     * after performing the given action.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which exception is used in the
-     * returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param action the action to perform before completing the
@@ -2506,14 +2556,16 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the {@link ForkJoinPool#commonPool()}
-     * after this or the other given CompletableFuture complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when either this or the other given CompletableFuture completes,
+     * after performing the given action from a task running in the
+     * {@link ForkJoinPool#commonPool()}.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which exception is used in the
-     * returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param action the action to perform before completing the
@@ -2527,14 +2579,16 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed
-     * asynchronously using the given executor after this or the other
-     * given CompletableFuture complete.
-     * If this and/or the other CompletableFuture complete exceptionally,
+     * Returns a new CompletableFuture that is asynchronously completed
+     * when either this or the other given CompletableFuture completes,
+     * after performing the given action from a task running in the
+     * given executor.
+     *
+     * <p>If this and/or the other CompletableFuture complete exceptionally,
      * then the returned CompletableFuture may also do so, with a
      * CompletionException holding one of these exceptions as its cause.
-     * No guarantees are made about which exception is used in the
-     * returned CompletableFuture.
+     * No guarantees are made about which result or exception is used in
+     * the returned CompletableFuture.
      *
      * @param other the other CompletableFuture
      * @param action the action to perform before completing the
@@ -2596,9 +2650,10 @@
     }
 
     /**
-     * Returns a CompletableFuture (or an equivalent one) produced by
-     * the given function of the result of this CompletableFuture when
-     * completed.  If this CompletableFuture completes exceptionally,
+     * Returns a CompletableFuture (or an equivalent one) produced by the
+     * given function of the result of this CompletableFuture when completed.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding this exception as its cause.
      *
@@ -2616,7 +2671,9 @@
      * Returns a CompletableFuture (or an equivalent one) produced
      * asynchronously using the {@link ForkJoinPool#commonPool()} by
      * the given function of the result of this CompletableFuture when
-     * completed.  If this CompletableFuture completes exceptionally,
+     * completed.
+     *
+     * <p>If this CompletableFuture completes exceptionally,
      * then the returned CompletableFuture also does so, with a
      * CompletionException holding this exception as its cause.
      *
@@ -2634,8 +2691,9 @@
      * Returns a CompletableFuture (or an equivalent one) produced
      * asynchronously using the given executor by the given function
      * of the result of this CompletableFuture when completed.
-     * If this CompletableFuture completes exceptionally, then the
-     * returned CompletableFuture also does so, with a
+     *
+     * <p>If this CompletableFuture completes exceptionally,
+     * then the returned CompletableFuture also does so, with a
      * CompletionException holding this exception as its cause.
      *
      * @param fn the function returning a new CompletableFuture
@@ -2687,15 +2745,13 @@
                 }
                 else {
                     try {
-                        dst = fn.apply(t);
+                        if ((dst = fn.apply(t)) == null)
+                            ex = new NullPointerException();
                     } catch (Throwable rex) {
                         ex = rex;
                     }
-                    if (dst == null) {
+                    if (dst == null)
                         dst = new CompletableFuture<U>();
-                        if (ex == null)
-                            ex = new NullPointerException();
-                    }
                 }
             }
             if (e == null && ex != null)
@@ -2707,12 +2763,12 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed with
-     * the result of the given function of the exception triggering
-     * this CompletableFuture's completion when it completes
-     * exceptionally; Otherwise, if this CompletableFuture completes
-     * normally, then the returned CompletableFuture also completes
-     * normally with the same value.
+     * Returns a new CompletableFuture that is completed when this
+     * CompletableFuture completes, with the result of the given
+     * function of the exception triggering this CompletableFuture's
+     * completion when it completes exceptionally; otherwise, if this
+     * CompletableFuture completes normally, then the returned
+     * CompletableFuture also completes normally with the same value.
      *
      * @param fn the function to use to compute the value of the
      * returned CompletableFuture if this CompletableFuture completed
@@ -2756,12 +2812,12 @@
     }
 
     /**
-     * Creates and returns a CompletableFuture that is completed with
-     * the result of the given function of the result and exception of
-     * this CompletableFuture's completion when it completes.  The
-     * given function is invoked with the result (or {@code null} if
-     * none) and the exception (or {@code null} if none) of this
-     * CompletableFuture when complete.
+     * Returns a new CompletableFuture that is completed when this
+     * CompletableFuture completes, with the result of the given
+     * function of the result and exception of this CompletableFuture's
+     * completion.  The given function is invoked with the result (or
+     * {@code null} if none) and the exception (or {@code null} if none)
+     * of this CompletableFuture when complete.
      *
      * @param fn the function to use to compute the value of the
      * returned CompletableFuture
@@ -2819,13 +2875,13 @@
 
     /**
      * Returns a new CompletableFuture that is completed when all of
-     * the given CompletableFutures complete.  If any of the component
+     * the given CompletableFutures complete.  If any of the given
      * CompletableFutures complete exceptionally, then so does the
      * returned CompletableFuture. Otherwise, the results, if any, of
-     * the component CompletableFutures are not reflected in the
-     * returned CompletableFuture, but may be obtained by inspecting
-     * them individually. If the number of components is zero, returns
-     * a CompletableFuture completed with the value {@code null}.
+     * the given CompletableFutures are not reflected in the returned
+     * CompletableFuture, but may be obtained by inspecting them
+     * individually. If no CompletableFutures are provided, returns a
+     * CompletableFuture completed with the value {@code null}.
      *
      * <p>Among the applications of this method is to await completion
      * of a set of independent CompletableFutures before continuing a
@@ -2833,7 +2889,7 @@
      * c3).join();}.
      *
      * @param cfs the CompletableFutures
-     * @return a CompletableFuture that is complete when all of the
+     * @return a new CompletableFuture that is completed when all of the
      * given CompletableFutures complete
      * @throws NullPointerException if the array or any of its elements are
      * {@code null}
@@ -2919,12 +2975,13 @@
 
     /**
      * Returns a new CompletableFuture that is completed when any of
-     * the component CompletableFutures complete; with the same result if
-     * it completed normally, otherwise exceptionally. If the number
-     * of components is zero, returns an incomplete CompletableFuture.
+     * the given CompletableFutures complete; with the same result if
+     * it completed normally, otherwise exceptionally. If no
+     * CompletableFutures are provided, returns an incomplete
+     * CompletableFuture.
      *
      * @param cfs the CompletableFutures
-     * @return a CompletableFuture that is complete when any of the
+     * @return a new CompletableFuture that is completed when any of the
      * given CompletableFutures complete
      * @throws NullPointerException if the array or any of its elements are
      * {@code null}
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Mon Mar 18 22:09:50 2013 -0700
@@ -2670,7 +2670,7 @@
      * @return the mapping for the key, if present; else the defaultValue
      * @throws NullPointerException if the specified key is null
      */
-    public V getValueOrDefault(Object key, V defaultValue) {
+    public V getOrDefault(Object key, V defaultValue) {
         V v;
         return (v = internalGet(key)) == null ? defaultValue : v;
     }
--- a/src/share/classes/java/util/concurrent/ConcurrentMap.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/ConcurrentMap.java	Mon Mar 18 22:09:50 2013 -0700
@@ -91,7 +91,7 @@
      * Removes the entry for a key only if currently mapped to a given value.
      * This is equivalent to
      *  <pre> {@code
-     * if (map.containsKey(key) && map.get(key).equals(value)) {
+     * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
      *   map.remove(key);
      *   return true;
      * } else
@@ -117,7 +117,7 @@
      * Replaces the entry for a key only if currently mapped to a given value.
      * This is equivalent to
      *  <pre> {@code
-     * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
+     * if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) {
      *   map.put(key, newValue);
      *   return true;
      * } else
--- a/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/ConcurrentNavigableMap.java	Mon Mar 18 22:09:50 2013 -0700
@@ -101,7 +101,7 @@
      * reflected in the descending map, and vice-versa.
      *
      * <p>The returned map has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code m.descendingMap().descendingMap()} returns a
      * view of {@code m} essentially equivalent to {@code m}.
      *
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Mon Mar 18 22:09:50 2013 -0700
@@ -1869,6 +1869,22 @@
     }
 
     /**
+     * Returns the value to which the specified key is mapped,
+     * or the given defaultValue if this map contains no mapping for the key.
+     *
+     * @param key the key
+     * @param defaultValue the value to return if this map contains
+     * no mapping for the given key
+     * @return the mapping for the key, if present; else the defaultValue
+     * @throws NullPointerException if the specified key is null
+     * @since 1.8
+     */
+    public V getOrDefault(Object key, V defaultValue) {
+        V v;
+        return (v = get(key)) == null ? defaultValue : v;
+    }
+
+    /**
      * Associates the specified value with the specified key in this map.
      * If the map previously contained a mapping for the key, the old
      * value is replaced.
@@ -2655,7 +2671,6 @@
         public NavigableSet<E> descendingSet() {
             return new KeySet<E>(m.descendingMap());
         }
-
         @SuppressWarnings("unchecked")
         public Spliterator<E> spliterator() {
             if (m instanceof ConcurrentSkipListMap)
@@ -2691,7 +2706,6 @@
         }
         public Object[] toArray()     { return toList(this).toArray();  }
         public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
-
         @SuppressWarnings("unchecked")
         public Spliterator<E> spliterator() {
             if (m instanceof ConcurrentSkipListMap)
@@ -3574,7 +3588,6 @@
         public NavigableSet<K> descendingSet() {
             return new KeySet<K>(m.descendingMap());
         }
-
         public Spliterator<K> spliterator() {
             return m.keySpliterator();
         }
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Mon Mar 18 22:09:50 2013 -0700
@@ -100,7 +100,7 @@
     /**
      * The underlying map. Uses Boolean.TRUE as value for each
      * element.  This field is declared final for the sake of thread
-     * safety, which entails some ugliness in clone()
+     * safety, which entails some ugliness in clone().
      */
     private final ConcurrentNavigableMap<E,Object> m;
 
@@ -470,7 +470,7 @@
      * reflected in the descending set, and vice-versa.
      *
      * <p>The returned set has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code s.descendingSet().descendingSet()} returns a
      * view of {@code s} essentially equivalent to {@code s}.
      *
--- a/src/share/classes/java/util/concurrent/CyclicBarrier.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/CyclicBarrier.java	Mon Mar 18 22:09:50 2013 -0700
@@ -347,7 +347,7 @@
      * the broken state.
      *
      * @return the arrival index of the current thread, where index
-     *         <tt>{@link #getParties()} - 1</tt> indicates the first
+     *         {@code getParties() - 1} indicates the first
      *         to arrive and zero indicates the last to arrive
      * @throws InterruptedException if the current thread was interrupted
      *         while waiting
@@ -416,7 +416,7 @@
      * @param timeout the time to wait for the barrier
      * @param unit the time unit of the timeout parameter
      * @return the arrival index of the current thread, where index
-     *         <tt>{@link #getParties()} - 1</tt> indicates the first
+     *         {@code getParties() - 1} indicates the first
      *         to arrive and zero indicates the last to arrive
      * @throws InterruptedException if the current thread was interrupted
      *         while waiting
--- a/src/share/classes/java/util/concurrent/ForkJoinPool.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java	Mon Mar 18 22:09:50 2013 -0700
@@ -139,6 +139,7 @@
  * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
  * - the class name of a {@link UncaughtExceptionHandler}
  * </ul>
+ * The system class loader is used to load these classes.
  * Upon any error in establishing these settings, default parameters
  * are used. It is possible to disable or limit the use of threads in
  * the common pool by setting the parallelism property to zero, and/or
@@ -188,32 +189,35 @@
      * (http://research.sun.com/scalable/pubs/index.html) and
      * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
      * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
-     * The main differences ultimately stem from GC requirements that
-     * we null out taken slots as soon as we can, to maintain as small
-     * a footprint as possible even in programs generating huge
-     * numbers of tasks. To accomplish this, we shift the CAS
-     * arbitrating pop vs poll (steal) from being on the indices
-     * ("base" and "top") to the slots themselves.  So, both a
-     * successful pop and poll mainly entail a CAS of a slot from
-     * non-null to null.  Because we rely on CASes of references, we
-     * do not need tag bits on base or top.  They are simple ints as
-     * used in any circular array-based queue (see for example
-     * ArrayDeque).  Updates to the indices must still be ordered in a
-     * way that guarantees that top == base means the queue is empty,
-     * but otherwise may err on the side of possibly making the queue
-     * appear nonempty when a push, pop, or poll have not fully
-     * committed. Note that this means that the poll operation,
-     * considered individually, is not wait-free. One thief cannot
-     * successfully continue until another in-progress one (or, if
-     * previously empty, a push) completes.  However, in the
-     * aggregate, we ensure at least probabilistic non-blockingness.
-     * If an attempted steal fails, a thief always chooses a different
-     * random victim target to try next. So, in order for one thief to
-     * progress, it suffices for any in-progress poll or new push on
-     * any empty queue to complete. (This is why we normally use
-     * method pollAt and its variants that try once at the apparent
-     * base index, else consider alternative actions, rather than
-     * method poll.)
+     * See also "Correct and Efficient Work-Stealing for Weak Memory
+     * Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
+     * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
+     * analysis of memory ordering (atomic, volatile etc) issues.  The
+     * main differences ultimately stem from GC requirements that we
+     * null out taken slots as soon as we can, to maintain as small a
+     * footprint as possible even in programs generating huge numbers
+     * of tasks. To accomplish this, we shift the CAS arbitrating pop
+     * vs poll (steal) from being on the indices ("base" and "top") to
+     * the slots themselves.  So, both a successful pop and poll
+     * mainly entail a CAS of a slot from non-null to null.  Because
+     * we rely on CASes of references, we do not need tag bits on base
+     * or top.  They are simple ints as used in any circular
+     * array-based queue (see for example ArrayDeque).  Updates to the
+     * indices must still be ordered in a way that guarantees that top
+     * == base means the queue is empty, but otherwise may err on the
+     * side of possibly making the queue appear nonempty when a push,
+     * pop, or poll have not fully committed. Note that this means
+     * that the poll operation, considered individually, is not
+     * wait-free. One thief cannot successfully continue until another
+     * in-progress one (or, if previously empty, a push) completes.
+     * However, in the aggregate, we ensure at least probabilistic
+     * non-blockingness.  If an attempted steal fails, a thief always
+     * chooses a different random victim target to try next. So, in
+     * order for one thief to progress, it suffices for any
+     * in-progress poll or new push on any empty queue to
+     * complete. (This is why we normally use method pollAt and its
+     * variants that try once at the apparent base index, else
+     * consider alternative actions, rather than method poll.)
      *
      * This approach also enables support of a user mode in which local
      * task processing is in FIFO, not LIFO order, simply by using
@@ -484,8 +488,11 @@
      * fullExternalPush during the first submission to the pool.
      *
      * When external threads submit to the common pool, they can
-     * perform some subtask processing (see externalHelpJoin and
-     * related methods).  We do not need to record whether these
+     * perform subtask processing (see externalHelpJoin and related
+     * methods).  This caller-helps policymakes it sensible to set
+     * common pool parallelism level to one (or more) less than the
+     * total number of available cores, or even zero for pure
+     * caller-runs.  We do not need to record whether external
      * submissions are to the common pool -- if not, externalHelpJoin
      * returns quickly (at the most helping to signal some common pool
      * workers). These submitters would otherwise be blocked waiting
--- a/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java	Mon Mar 18 22:09:50 2013 -0700
@@ -65,7 +65,7 @@
  * <p>Class {@link DoubleAdder} provides analogs of the functionality
  * of this class for the common special case of maintaining sums.  The
  * call {@code new DoubleAdder()} is equivalent to {@code new
- * DoubleAccumulator((x, y) -> x + y, 0.0}.
+ * DoubleAccumulator((x, y) -> x + y, 0.0)}.
  *
  * <p>This class extends {@link Number}, but does <em>not</em> define
  * methods such as {@code equals}, {@code hashCode} and {@code
--- a/src/share/classes/java/util/concurrent/package-info.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/concurrent/package-info.java	Mon Mar 18 22:09:50 2013 -0700
@@ -102,8 +102,10 @@
  * <h2>Queues</h2>
  *
  * The {@link java.util.concurrent.ConcurrentLinkedQueue} class
- * supplies an efficient scalable thread-safe non-blocking FIFO
- * queue.
+ * supplies an efficient scalable thread-safe non-blocking FIFO queue.
+ * The {@link java.util.concurrent.ConcurrentLinkedDeque} class is
+ * similar, but additionally supports the {@link java.util.Deque}
+ * interface.
  *
  * <p>Five implementations in {@code java.util.concurrent} support
  * the extended {@link java.util.concurrent.BlockingQueue}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/DoubleToIntFunction.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.function;
+
+/**
+ * Apply a function to the input argument, yielding an appropriate result.
+ * This is the {@code double}-to-{@code int} specialization for {@link Function}.
+ *
+ * @see Function
+ * @since 1.8
+ */
+@FunctionalInterface
+public interface DoubleToIntFunction {
+
+    /**
+     * Compute the result of applying the function to the input arguments.
+     *
+     * @param value the input value
+     * @return the function result value
+     */
+    public int applyAsInt(double value);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/DoubleToLongFunction.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.function;
+
+/**
+ * Apply a function to the input argument, yielding an appropriate result.
+ * This is the {@code double}-to-{@code long} specialization for {@link Function}.
+ *
+ * @see Function
+ * @since 1.8
+ */
+@FunctionalInterface
+public interface DoubleToLongFunction {
+
+    /**
+     * Compute the result of applying the function to the input arguments.
+     *
+     * @param value the input value
+     * @return the function result value
+     */
+    public long applyAsLong(double value);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/IntToDoubleFunction.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.function;
+
+/**
+ * Apply a function to the input argument, yielding an appropriate result.
+ * This is the {@code int}-to-{@code double} specialization for {@link Function}.
+ *
+ * @see Function
+ * @since 1.8
+ */
+@FunctionalInterface
+public interface IntToDoubleFunction {
+
+    /**
+     * Compute the result of applying the function to the input arguments.
+     *
+     * @param value the input value
+     * @return the function result value
+     */
+    public double applyAsDouble(int value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/IntToLongFunction.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.function;
+
+/**
+ * Apply a function to the input argument, yielding an appropriate result.
+ * This is the {@code int}-to-{@code long} specialization for {@link Function}.
+ *
+ * @see Function
+ * @since 1.8
+ */
+@FunctionalInterface
+public interface IntToLongFunction {
+
+    /**
+     * Compute the result of applying the function to the input arguments.
+     *
+     * @param value the input value
+     * @return the function result value
+     */
+    public long applyAsLong(int value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/LongToDoubleFunction.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.function;
+
+/**
+ * Apply a function to the input argument, yielding an appropriate result.
+ * This is the {@code long}-to-{@code double} specialization for {@link Function}.
+ *
+ * @see Function
+ * @since 1.8
+ */
+@FunctionalInterface
+public interface LongToDoubleFunction {
+
+    /**
+     * Compute the result of applying the function to the input arguments.
+     *
+     * @param value the input value
+     * @return the function result value
+     */
+    public double applyAsDouble(long value);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/LongToIntFunction.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.function;
+
+/**
+ * Apply a function to the input argument, yielding an appropriate result.
+ * This is the {@code long}-to-{@code int} specialization for {@link Function}.
+ *
+ * @see Function
+ * @since 1.8
+ */
+@FunctionalInterface
+public interface LongToIntFunction {
+
+    /**
+     * Compute the result of applying the function to the input arguments.
+     *
+     * @param value the input value
+     * @return the function result value
+     */
+    public int applyAsInt(long value);
+}
+
--- a/src/share/classes/java/util/stream/Collector.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/Collector.java	Mon Mar 18 22:09:50 2013 -0700
@@ -111,37 +111,4 @@
      * @return True if this collector is stable
      */
     default boolean isStable() { return false; }
-
-    interface OfInt<R> extends Collector<Integer, R> {
-        ObjIntConsumer<R> intAccumulator();
-
-        @Override
-        default BiFunction<R, Integer, R> accumulator() {
-            if (Tripwire.ENABLED)
-                Tripwire.trip(getClass(), "{0} calling Collector.OfInt.accumulator()");
-            return (r, i) -> { intAccumulator().accept(r, i); return r; };
-        }
-    }
-
-    interface OfLong<R> extends Collector<Long, R> {
-        ObjLongConsumer<R> longAccumulator();
-
-        @Override
-        default BiFunction<R, Long, R> accumulator() {
-            if (Tripwire.ENABLED)
-                Tripwire.trip(getClass(), "{0} calling Collector.OfLong.accumulator()");
-            return (r, l) -> { longAccumulator().accept(r, l); return r; };
-        }
-    }
-
-    interface OfDouble<R> extends Collector<Double, R> {
-        ObjDoubleConsumer<R> doubleAccumulator();
-
-        @Override
-        default BiFunction<R, Double, R> accumulator() {
-            if (Tripwire.ENABLED)
-                Tripwire.trip(getClass(), "{0} calling Collector.OfDouble.accumulator()");
-            return (r, d) -> { doubleAccumulator().accept(r, d); return r; };
-        }
-    }
 }
--- a/src/share/classes/java/util/stream/Collectors.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/Collectors.java	Mon Mar 18 22:09:50 2013 -0700
@@ -28,6 +28,7 @@
 import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -35,22 +36,14 @@
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
-import java.util.OptionalDouble;
-import java.util.OptionalLong;
 import java.util.Set;
 import java.util.StringJoiner;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.BinaryOperator;
-import java.util.function.DoubleConsumer;
 import java.util.function.Function;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-import java.util.function.ObjDoubleConsumer;
-import java.util.function.ObjIntConsumer;
-import java.util.function.ObjLongConsumer;
+import java.util.function.IntBinaryOperator;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.function.ToDoubleFunction;
@@ -134,60 +127,6 @@
         }
     }
 
-    static final class IntCollectorImpl<R>
-            extends AbstractCollectorImpl<Integer, R> implements Collector.OfInt<R> {
-        private final ObjIntConsumer<R> intAccumulator;
-
-        IntCollectorImpl(Supplier<R> resultSupplier,
-                         ObjIntConsumer<R> accumulator,
-                         BinaryOperator<R> combiner,
-                         boolean isConcurrent) {
-            super(resultSupplier, combiner, isConcurrent, true);
-            this.intAccumulator = accumulator;
-        }
-
-        @Override
-        public ObjIntConsumer<R> intAccumulator() {
-            return intAccumulator;
-        }
-    }
-
-    static final class DoubleCollectorImpl<R>
-            extends AbstractCollectorImpl<Double, R> implements Collector.OfDouble<R> {
-        private final ObjDoubleConsumer<R> doubleAccumulator;
-
-        DoubleCollectorImpl(Supplier<R> resultSupplier,
-                            ObjDoubleConsumer<R> accumulator,
-                            BinaryOperator<R> combiner,
-                            boolean isConcurrent) {
-            super(resultSupplier, combiner, isConcurrent, true);
-            this.doubleAccumulator = accumulator;
-        }
-
-        @Override
-        public ObjDoubleConsumer<R> doubleAccumulator() {
-            return doubleAccumulator;
-        }
-    }
-
-    static final class LongCollectorImpl<R>
-            extends AbstractCollectorImpl<Long, R> implements Collector.OfLong<R> {
-        private final ObjLongConsumer<R> longAccumulator;
-
-        LongCollectorImpl(Supplier<R> resultSupplier,
-                          ObjLongConsumer<R> accumulator,
-                          BinaryOperator<R> combiner,
-                          boolean isConcurrent) {
-            super(resultSupplier, combiner, isConcurrent, true);
-            this.longAccumulator = accumulator;
-        }
-
-        @Override
-        public ObjLongConsumer<R> longAccumulator() {
-            return longAccumulator;
-        }
-    }
-
     /**
      * Accumulate elements into a new {@code Collection}, which is created by the provided factory.
      *
@@ -215,8 +154,35 @@
      */
     public static<T>
     Collector<T, List<T>> toList() {
-        // Consider a tree-based List?
-        return toCollection(ArrayList::new);
+        BiFunction<List<T>, T, List<T>> accumulator = (list, t) -> {
+            switch (list.size()) {
+                case 0:
+                    return Collections.singletonList(t);
+                case 1:
+                    List<T> newList = new ArrayList<>();
+                    newList.add(list.get(0));
+                    newList.add(t);
+                    return newList;
+                default:
+                    list.add(t);
+                    return list;
+            }
+        };
+        BinaryOperator<List<T>> combiner = (left, right) -> {
+            switch (left.size()) {
+                case 0:
+                    return right;
+                case 1:
+                    List<T> newList = new ArrayList<>(left.size() + right.size());
+                    newList.addAll(left);
+                    newList.addAll(right);
+                    return newList;
+                default:
+                    left.addAll(right);
+                    return left;
+            }
+        };
+        return new CollectorImpl<>(Collections::emptyList, accumulator, combiner, false, false);
     }
 
     /**
@@ -299,33 +265,16 @@
                                    downstream.combiner(), downstream.isConcurrent(), downstream.isStable());
     }
 
-    public static <T, R> Collector<T, R>
-    mapping(ToIntFunction<? super T> mapper, Collector.OfInt<R> downstream) {
-        ObjIntConsumer<R> downstreamAccumulator = downstream.intAccumulator();
-        return new CollectorImpl<>(downstream.resultSupplier(),
-                                   (r, t) -> { downstreamAccumulator.accept(r, mapper.applyAsInt(t)); return r; },
-                                   downstream.combiner(), downstream.isConcurrent(), downstream.isStable());
+    public static <T> Collector<T, T>
+    reducing(BinaryOperator<T> op) {
+        return new CollectorImpl<>(() -> null, (r, t) -> (r == null ? t : op.apply(r, t)), op, false, false);
     }
 
-    public static <T, R> Collector<T, R>
-    mapping(ToDoubleFunction<? super T> mapper, Collector.OfDouble<R> downstream) {
-        ObjDoubleConsumer<R> downstreamAccumulator = downstream.doubleAccumulator();
-        return new CollectorImpl<>(downstream.resultSupplier(),
-                                   (r, t) -> { downstreamAccumulator.accept(r, mapper.applyAsDouble(t)); return r; },
-                                   downstream.combiner(), downstream.isConcurrent(), downstream.isStable());
-    }
-
-    public static <T, R> Collector<T, R>
-    mapping(ToLongFunction<? super T> mapper, Collector.OfLong<R> downstream) {
-        ObjLongConsumer<R> downstreamAccumulator = downstream.longAccumulator();
-        return new CollectorImpl<>(downstream.resultSupplier(),
-                                   (r, t) -> { downstreamAccumulator.accept(r, mapper.applyAsLong(t)); return r; },
-                                   downstream.combiner(), downstream.isConcurrent(), downstream.isStable());
-    }
-
-    public static <T> Collector<T, T>
-    reducing(BinaryOperator<T> op) {
-        return new CollectorImpl<>(() -> null, (r, t) -> (r == null ? t : op.apply(t, r)), op, false, false);
+    public static <T, U> Collector<T, U>
+    reducing(Function<? super T, ? extends U> mapper, BinaryOperator<U> op) {
+        return new CollectorImpl<>(() -> null,
+                                   (r, t) -> (r == null ? mapper.apply(t) : op.apply(r, mapper.apply(t))),
+                                   op, false, false);
     }
 
     public static<T, K> Collector<T, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) {
@@ -390,7 +339,7 @@
                 downstreamAccumulator.apply(m.computeIfAbsent(key, k -> downstreamSupplier.get()), t);
                 return m;
             };
-            return new Collectors.CollectorImpl<>(mapFactory, accumulator, leftMapMerger(downstream.combiner()), true, true);
+            return new CollectorImpl<>(mapFactory, accumulator, leftMapMerger(downstream.combiner()), true, true);
         }
         else if (downstream.isStable()) {
             BiFunction<M, T, M> accumulator = (m, t) -> {
@@ -401,7 +350,7 @@
                 }
                 return m;
             };
-            return new Collectors.CollectorImpl<>(mapFactory, accumulator, leftMapMerger(downstream.combiner()), true, true);
+            return new CollectorImpl<>(mapFactory, accumulator, leftMapMerger(downstream.combiner()), true, true);
         }
         else {
             BiFunction<M, T, M> accumulator = (m, t) -> {
@@ -410,21 +359,21 @@
                     D oldResult = m.computeIfAbsent(key, k -> downstreamSupplier.get());
                     if (oldResult == null) {
                         if (m.putIfAbsent(key, downstreamAccumulator.apply(null, t)) == null)
-                        return m;
+                            return m;
                     }
                     else {
-                        D newResult;
                         synchronized (oldResult) {
-                            newResult = downstreamAccumulator.apply(oldResult, t);
+                            if (m.get(key) != oldResult)
+                                continue;
+                            D newResult = downstreamAccumulator.apply(oldResult, t);
+                            if (oldResult != newResult)
+                                m.put(key, newResult);
+                            return m;
                         }
-                        if (oldResult == newResult)
-                            return m;
-                        else if (m.replace(key, oldResult, newResult))
-                            return m;
                     }
                 } while (true);
             };
-            return new Collectors.CollectorImpl<>(mapFactory, accumulator, leftMapMerger(downstream.combiner()), true, true);
+            return new CollectorImpl<>(mapFactory, accumulator, leftMapMerger(downstream.combiner()), true, true);
         }
     }
 
@@ -539,7 +488,22 @@
                                     Supplier<M> mapSupplier,
                                     BinaryOperator<U> mergeFunction) {
         BiFunction<M, T, M> accumulator = (map, value) -> { map.merge(value, mapper.apply(value), mergeFunction); return map; };
-        return new Collectors.CollectorImpl<>(mapSupplier, accumulator, Collectors.leftMapMerger(mergeFunction), true, true);
+        return new CollectorImpl<>(mapSupplier, accumulator, leftMapMerger(mergeFunction), true, true);
+    }
+
+    public static<T> Collector<T, IntStatistics> toIntStatistics(ToIntFunction<? super T> mapper) {
+        return new CollectorImpl<>(IntStatistics::new, (r, t) -> { r.accept(mapper.applyAsInt(t)); return r; },
+                                   (l, r) -> { l.combine(r); return l; }, false, true);
+    }
+
+    public static<T> Collector<T, LongStatistics> toLongStatistics(ToLongFunction<? super T> mapper) {
+        return new CollectorImpl<>(LongStatistics::new, (r, t) -> { r.accept(mapper.applyAsLong(t)); return r; },
+                                   (l, r) -> { l.combine(r); return l; }, false, true);
+    }
+
+    public static<T> Collector<T, DoubleStatistics> toDoubleStatistics(ToDoubleFunction<? super T> mapper) {
+        return new CollectorImpl<>(DoubleStatistics::new, (r, t) -> { r.accept(mapper.applyAsDouble(t)); return r; },
+                                   (l, r) -> { l.combine(r); return l; }, false, true);
     }
 
     static final class Partition<T> extends AbstractMap<Boolean, T> implements Map<Boolean, T> {
@@ -609,142 +573,15 @@
         return (m1, m2) -> {
             Partition<D> left = (Partition<D>) m1;
             Partition<D> right = (Partition<D>) m2;
-            left.forFalse = op.apply(left.forFalse, right.forFalse);
-            left.forTrue = op.apply(left.forTrue, right.forTrue);
+            if (left.forFalse == null)
+                left.forFalse = right.forFalse;
+            else if (right.forFalse != null)
+                left.forFalse = op.apply(left.forFalse, right.forFalse);
+            if (left.forTrue == null)
+                left.forTrue = right.forTrue;
+            else if (right.forTrue != null)
+                left.forTrue = op.apply(left.forTrue, right.forTrue);
             return left;
         };
     }
-
-    /**
-     * A state object for collecting statistics such as count, min, max, sum, and average for {@code long} values.
-     */
-    public static final class LongStatistics implements LongConsumer, IntConsumer {
-        private long count;
-        private long sum;
-        private long min = Long.MAX_VALUE;
-        private long max = Long.MIN_VALUE;
-
-        @Override
-        public void accept(int value) {
-            accept((long) value);
-        }
-
-        @Override
-        public void accept(long value) {
-            ++count;
-            sum += value;
-            min = Math.min(min, value);
-            max = Math.max(max, value);
-        }
-
-        private void combine(LongStatistics other) {
-            count += other.count;
-            sum += other.sum;
-            min = Math.min(min, other.min);
-            max = Math.min(max, other.max);
-        }
-
-        public long getCount() {
-            return count;
-        }
-
-        public long getSum() {
-            return sum;
-        }
-
-        public OptionalLong getMin() {
-            return count > 0 ? OptionalLong.of(min) : OptionalLong.empty();
-        }
-
-        public OptionalLong getMax() {
-            return count > 0 ? OptionalLong.of(max) : OptionalLong.empty();
-        }
-
-        public OptionalDouble getMean() {
-            return count > 0 ? OptionalDouble.of((double) sum / count) : OptionalDouble.empty();
-        }
-
-        @Override
-        public String toString() {
-            return new StringJoiner(", ", this.getClass().getSimpleName() + "{", "}")
-            .add("count=" + getCount())
-                    .add("sum=" + getSum())
-                    .add("min=" + getMin())
-                    .add("max=" + getMax())
-                    .toString();
-        }
-    }
-
-    /**
-     * A state object for collecting statistics such as count, min, max, sum, and average for {@code double} values.
-     */
-    public static final class DoubleStatistics implements DoubleConsumer {
-        private long count;
-        private double sum;
-        private double min = Double.POSITIVE_INFINITY;
-        private double max = Double.NEGATIVE_INFINITY;
-
-        @Override
-        public void accept(double value) {
-            ++count;
-            sum += value;
-            min = Math.min(min, value);
-            max = Math.max(max, value);
-        }
-
-        private void combine(DoubleStatistics other) {
-            count += other.count;
-            sum += other.sum;
-            min = Math.min(min, other.min);
-            max = Math.min(max, other.max);
-        }
-
-        public long getCount() {
-            return count;
-        }
-
-        public double getSum() {
-            return sum;
-        }
-
-        public OptionalDouble getMin() {
-            return count > 0 ? OptionalDouble.of(min) : OptionalDouble.empty();
-        }
-
-        public OptionalDouble getMax() {
-            return count > 0 ? OptionalDouble.of(max) : OptionalDouble.empty();
-        }
-
-        public OptionalDouble getMean() {
-            return count > 0 ? OptionalDouble.of(sum / count) : OptionalDouble.empty();
-        }
-
-        @Override
-        public String toString() {
-            return new StringJoiner(", ", this.getClass().getSimpleName() + "{", "}")
-                    .add("count=" + getCount())
-                    .add("sum=" + getSum())
-                    .add("min=" + getMin())
-                    .add("max=" + getMax())
-                    .toString();
-        }
-    }
-
-    /**
-     * Collect summary statistics for a set of {@code long} values.
-     * @return A {@code Collector} which summarizes {@code long} values into a {@link LongStatistics}
-     */
-    public static Collector.OfLong<LongStatistics> toLongStatistics() {
-        return new LongCollectorImpl<>(LongStatistics::new, LongStatistics::accept,
-                                      (l, r) -> { l.combine(r); return l; }, false);
-    }
-
-    /**
-     * Collect summary statistics for a set of {@code double} values.
-     * @return A {@code Collector} which summarizes {@code double} values into a {@link DoubleStatistics}
-     */
-    public static Collector.OfDouble<DoubleStatistics> toDoubleStatistics() {
-        return new DoubleCollectorImpl<>(DoubleStatistics::new, DoubleStatistics::accept,
-                                         (l, r) -> { l.combine(r); return l; }, false);
-    }
 }
--- a/src/share/classes/java/util/stream/DoublePipeline.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/DoublePipeline.java	Mon Mar 18 22:09:50 2013 -0700
@@ -36,10 +36,11 @@
 import java.util.function.DoubleConsumer;
 import java.util.function.DoubleFunction;
 import java.util.function.DoublePredicate;
+import java.util.function.DoubleToIntFunction;
+import java.util.function.DoubleToLongFunction;
 import java.util.function.DoubleUnaryOperator;
 import java.util.function.IntFunction;
 import java.util.function.ObjDoubleConsumer;
-import java.util.function.ObjIntConsumer;
 import java.util.function.Supplier;
 
 /**
@@ -98,7 +99,7 @@
 
     @Override
     protected <T> AbstractPipeline<?, T, ?> stream(Supplier<? extends Spliterator<?>> supplier, int flags) {
-        return new DoublePipeline((Supplier<? extends Spliterator<Double>>) supplier, flags);
+        return new DoublePipeline(supplier, flags);
     }
 
     @Override
@@ -131,7 +132,7 @@
 
     @Override
     public Stream<Double> boxed() {
-        return map(i -> Double.valueOf(i));
+        return map(Double::valueOf);
     }
 
     static Spliterator.OfDouble adapt(Spliterator<Double> s) {
@@ -177,6 +178,30 @@
     }
 
     @Override
+    public IntStream map(DoubleToIntFunction mapper) {
+        Objects.requireNonNull(mapper);
+        return chainedToInt(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, StreamShape.DOUBLE_VALUE,
+                            (flags, sink) -> new Sink.ChainedDouble(sink) {
+                                @Override
+                                public void accept(double t) {
+                                    downstream.accept(mapper.applyAsInt(t));
+                                }
+                            });
+    }
+
+    @Override
+    public LongStream map(DoubleToLongFunction mapper) {
+        Objects.requireNonNull(mapper);
+        return chainedToLong(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, StreamShape.DOUBLE_VALUE,
+                             (flags, sink) -> new Sink.ChainedDouble(sink) {
+                                 @Override
+                                 public void accept(double t) {
+                                     downstream.accept(mapper.applyAsLong(t));
+                                 }
+                             });
+    }
+
+    @Override
     public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
         return flatMap((double i, DoubleConsumer sink) -> mapper.apply(i).sequential().forEach(sink));
     }
@@ -287,7 +312,16 @@
 
     @Override
     public OptionalDouble average() {
-        return collect(Collectors.toDoubleStatistics()).getMean();
+        double[] avg = collect(() -> new double[2],
+                               (ll, i) -> {
+                                   ll[0]++;
+                                   ll[1] += i;
+                               },
+                               (ll, rr) -> {
+                                   ll[0] += rr[0];
+                                   ll[1] += rr[1];
+                               });
+        return avg[0] > 0 ? OptionalDouble.of(avg[1] / avg[0]) : OptionalDouble.empty();
     }
 
     @Override
@@ -296,6 +330,11 @@
     }
 
     @Override
+    public DoubleStatistics statistics() {
+        return collect(DoubleStatistics::new, DoubleStatistics::accept, DoubleStatistics::combine);
+    }
+
+    @Override
     public double reduce(double identity, DoubleBinaryOperator op) {
         return pipeline(ReduceOps.makeDouble(identity, op));
     }
@@ -311,25 +350,7 @@
             combiner.accept(left, right);
             return left;
         };
-        return collect(new Collectors.DoubleCollectorImpl<>(resultFactory, accumulator, operator, false));
-    }
-
-    @Override
-    public <R> R collect(Collector.OfDouble<R> collector) {
-        return pipeline(ReduceOps.makeDouble(collector));
-    }
-
-    @Override
-    public <R> R collectUnordered(Collector.OfDouble<R> collector) {
-        if (collector.isConcurrent()) {
-            R container = collector.resultSupplier().get();
-            ObjDoubleConsumer<R> accumulator = collector.doubleAccumulator();
-            forEach(u -> accumulator.accept(container, u));
-            return container;
-        }
-        else {
-            return collect(collector);
-        }
+        return pipeline(ReduceOps.makeDouble(resultFactory, accumulator, operator));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/stream/DoubleStatistics.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.stream;
+
+import java.util.StringJoiner;
+import java.util.function.DoubleConsumer;
+
+/**
+ * A state object for collecting statistics such as count, min, max, sum, and average for {@code double} values.
+ */
+public class DoubleStatistics implements DoubleConsumer {
+    private long count;
+    private double sum;
+    private double min = Double.POSITIVE_INFINITY;
+    private double max = Double.NEGATIVE_INFINITY;
+
+    @Override
+    public void accept(double value) {
+        ++count;
+        sum += value;
+        min = Math.min(min, value);
+        max = Math.max(max, value);
+    }
+
+    public void combine(DoubleStatistics other) {
+        count += other.count;
+        sum += other.sum;
+        min = Math.min(min, other.min);
+        max = Math.min(max, other.max);
+    }
+
+    public long getCount() {
+        return count;
+    }
+
+    public double getSum() {
+        return sum;
+    }
+
+    public double getMin() {
+        return min;
+    }
+
+    public double getMax() {
+        return max;
+    }
+
+    public double getMean() {
+        return count > 0 ? sum / count : 0.0d;
+    }
+
+    @Override
+    public String toString() {
+        return new StringJoiner(", ", this.getClass().getSimpleName() + "{", "}")
+                .add("count=" + getCount())
+                .add("sum=" + getSum())
+                .add("min=" + getMin())
+                .add("max=" + getMax())
+                .toString();
+    }
+}
--- a/src/share/classes/java/util/stream/DoubleStream.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/DoubleStream.java	Mon Mar 18 22:09:50 2013 -0700
@@ -31,6 +31,8 @@
 import java.util.function.DoubleConsumer;
 import java.util.function.DoubleFunction;
 import java.util.function.DoublePredicate;
+import java.util.function.DoubleToIntFunction;
+import java.util.function.DoubleToLongFunction;
 import java.util.function.DoubleUnaryOperator;
 import java.util.function.ObjDoubleConsumer;
 import java.util.function.ObjIntConsumer;
@@ -57,6 +59,10 @@
 
     <U> Stream<U> map(DoubleFunction<U> mapper);
 
+    IntStream map(DoubleToIntFunction mapper);
+
+    LongStream map(DoubleToLongFunction mapper);
+
     DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper);
 
     DoubleStream flatMap(FlatMapper.OfDoubleToDouble mapper);
@@ -87,10 +93,6 @@
                   ObjDoubleConsumer<R> accumulator,
                   BiConsumer<R, R> combiner);
 
-    <R> R collect(Collector.OfDouble<R> collector);
-
-    <R> R collectUnordered(Collector.OfDouble<R> collector);
-
     boolean anyMatch(DoublePredicate predicate);
 
     boolean allMatch(DoublePredicate predicate);
@@ -115,5 +117,7 @@
 
     long count();
 
+    DoubleStatistics statistics();
+
     double[] toArray();
 }
--- a/src/share/classes/java/util/stream/IntPipeline.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/IntPipeline.java	Mon Mar 18 22:09:50 2013 -0700
@@ -37,6 +37,8 @@
 import java.util.function.IntConsumer;
 import java.util.function.IntFunction;
 import java.util.function.IntPredicate;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
 import java.util.function.IntUnaryOperator;
 import java.util.function.ObjIntConsumer;
 import java.util.function.Supplier;
@@ -97,7 +99,7 @@
 
     @Override
     protected <T> AbstractPipeline<?, T, ?> stream(Supplier<? extends Spliterator<?>> supplier, int flags) {
-        return new IntPipeline((Supplier<? extends Spliterator<Integer>>) supplier, flags);
+        return new IntPipeline(supplier, flags);
     }
 
     @Override
@@ -170,7 +172,7 @@
 
     @Override
     public Stream<Integer> boxed() {
-        return map(i -> Integer.valueOf(i));
+        return map(Integer::valueOf);
     }
 
     @Override
@@ -198,6 +200,30 @@
     }
 
     @Override
+    public LongStream map(IntToLongFunction mapper) {
+        Objects.requireNonNull(mapper);
+        return chainedToLong(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, StreamShape.INT_VALUE,
+                             (flags, sink) -> new Sink.ChainedInt(sink) {
+                                 @Override
+                                 public void accept(int t) {
+                                     downstream.accept(mapper.applyAsLong(t));
+                                 }
+                             });
+    }
+
+    @Override
+    public DoubleStream map(IntToDoubleFunction mapper) {
+        Objects.requireNonNull(mapper);
+        return chainedToDouble(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, StreamShape.INT_VALUE,
+                               (flags, sink) -> new Sink.ChainedInt(sink) {
+                                   @Override
+                                   public void accept(int t) {
+                                       downstream.accept(mapper.applyAsDouble(t));
+                                   }
+                               });
+    }
+
+    @Override
     public IntStream flatMap(IntFunction<? extends IntStream> mapper) {
         return flatMap((int i, IntConsumer sink) -> mapper.apply(i).sequential().forEach(sink));
     }
@@ -312,7 +338,21 @@
 
     @Override
     public OptionalDouble average() {
-        return longs().average();
+        long[] avg = collect(() -> new long[2],
+                             (ll, i) -> {
+                                 ll[0]++;
+                                 ll[1] += i;
+                             },
+                             (ll, rr) -> {
+                                 ll[0] += rr[0];
+                                 ll[1] += rr[1];
+                             });
+        return avg[0] > 0 ? OptionalDouble.of((double) avg[1] / avg[0]) : OptionalDouble.empty();
+    }
+
+    @Override
+    public IntStatistics statistics() {
+        return collect(IntStatistics::new, IntStatistics::accept, IntStatistics::combine);
     }
 
     @Override
@@ -331,25 +371,7 @@
             combiner.accept(left, right);
             return left;
         };
-        return collect(new Collectors.IntCollectorImpl<>(resultFactory, accumulator, operator, false));
-    }
-
-    @Override
-    public <R> R collect(Collector.OfInt<R> collector) {
-        return pipeline(ReduceOps.makeInt(collector));
-    }
-
-    @Override
-    public <R> R collectUnordered(Collector.OfInt<R> collector) {
-        if (collector.isConcurrent()) {
-            R container = collector.resultSupplier().get();
-            ObjIntConsumer<R> accumulator = collector.intAccumulator();
-            forEach(u -> accumulator.accept(container, u));
-            return container;
-        }
-        else {
-            return collect(collector);
-        }
+        return pipeline(ReduceOps.makeInt(resultFactory, accumulator, operator));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/stream/IntStatistics.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.stream;
+
+import java.util.StringJoiner;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+
+/**
+ * A state object for collecting statistics such as count, min, max, sum, and average for {@code int} values.
+ */
+public class IntStatistics implements IntConsumer {
+    private long count;
+    private int sum;
+    private int min = Integer.MIN_VALUE;
+    private int max = Integer.MAX_VALUE;
+
+    @Override
+    public void accept(int value) {
+        ++count;
+        sum += value;
+        min = Math.min(min, value);
+        max = Math.max(max, value);
+    }
+
+    public void combine(IntStatistics other) {
+        count += other.count;
+        sum += other.sum;
+        min = Math.min(min, other.min);
+        max = Math.min(max, other.max);
+    }
+
+    public long getCount() {
+        return count;
+    }
+
+    public int getSum() {
+        return sum;
+    }
+
+    public int getMin() {
+        return min;
+    }
+
+    public int getMax() {
+        return max;
+    }
+
+    public double getMean() {
+        return count > 0 ? sum / count : 0.0d;
+    }
+
+    @Override
+    public String toString() {
+        return new StringJoiner(", ", this.getClass().getSimpleName() + "{", "}")
+                .add("count=" + getCount())
+                .add("sum=" + getSum())
+                .add("min=" + getMin())
+                .add("max=" + getMax())
+                .toString();
+    }
+}
--- a/src/share/classes/java/util/stream/IntStream.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/IntStream.java	Mon Mar 18 22:09:50 2013 -0700
@@ -31,6 +31,8 @@
 import java.util.function.IntConsumer;
 import java.util.function.IntFunction;
 import java.util.function.IntPredicate;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
 import java.util.function.IntUnaryOperator;
 import java.util.function.ObjIntConsumer;
 import java.util.function.Supplier;
@@ -86,6 +88,22 @@
     <U> Stream<U> map(IntFunction<U> mapper);
 
     /**
+     * Transform this stream into one consisting of the result of applying the given function to the
+     * elements of this stream.  This is an <a href="package-summary.html#StreamOps">intermediate operation</a>.
+     * @param mapper The function to be applied to each element
+     * @return the new stream
+     */
+    LongStream map(IntToLongFunction mapper);
+
+    /**
+     * Transform this stream into one consisting of the result of applying the given function to the
+     * elements of this stream.  This is an <a href="package-summary.html#StreamOps">intermediate operation</a>.
+     * @param mapper The function to be applied to each element
+     * @return the new stream
+     */
+    DoubleStream map(IntToDoubleFunction mapper);
+
+    /**
      * Transform this stream into one where each element is replaced with the contents of the stream produced
      * by applying the provided function to that element.  This is
      * an <a href="package-summary.html#StreamOps">intermediate operation</a>.
@@ -146,10 +164,6 @@
                   ObjIntConsumer<R> accumulator,
                   BiConsumer<R, R> combiner);
 
-    <R> R collect(Collector.OfInt<R> collector);
-
-    <R> R collectUnordered(Collector.OfInt<R> collector);
-
     boolean anyMatch(IntPredicate predicate);
 
     boolean allMatch(IntPredicate predicate);
@@ -174,5 +188,7 @@
 
     OptionalDouble average();
 
+    IntStatistics statistics();
+
     int[] toArray();
 }
--- a/src/share/classes/java/util/stream/LongPipeline.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/LongPipeline.java	Mon Mar 18 22:09:50 2013 -0700
@@ -38,8 +38,9 @@
 import java.util.function.LongConsumer;
 import java.util.function.LongFunction;
 import java.util.function.LongPredicate;
+import java.util.function.LongToDoubleFunction;
+import java.util.function.LongToIntFunction;
 import java.util.function.LongUnaryOperator;
-import java.util.function.ObjIntConsumer;
 import java.util.function.ObjLongConsumer;
 import java.util.function.Supplier;
 
@@ -99,7 +100,7 @@
 
     @Override
     protected <T> AbstractPipeline<?, T, ?> stream(Supplier<? extends Spliterator<?>> supplier, int flags) {
-        return new LongPipeline((Supplier<? extends Spliterator<Long>>) supplier, flags);
+        return new LongPipeline(supplier, flags);
     }
 
     @Override
@@ -161,7 +162,7 @@
 
     @Override
     public Stream<Long> boxed() {
-        return map(i -> Long.valueOf(i));
+        return map(Long::valueOf);
     }
 
     @Override
@@ -189,6 +190,30 @@
     }
 
     @Override
+    public IntStream map(LongToIntFunction mapper) {
+        Objects.requireNonNull(mapper);
+        return chainedToInt(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, StreamShape.LONG_VALUE,
+                            (flags, sink) -> new Sink.ChainedLong(sink) {
+                                @Override
+                                public void accept(long t) {
+                                    downstream.accept(mapper.applyAsInt(t));
+                                }
+                            });
+    }
+
+    @Override
+    public DoubleStream map(LongToDoubleFunction mapper) {
+        Objects.requireNonNull(mapper);
+        return chainedToDouble(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, StreamShape.LONG_VALUE,
+                               (flags, sink) -> new Sink.ChainedLong(sink) {
+                                   @Override
+                                   public void accept(long t) {
+                                       downstream.accept(mapper.applyAsDouble(t));
+                                   }
+                               });
+    }
+
+    @Override
     public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
         return flatMap((long i, LongConsumer sink) -> mapper.apply(i).sequential().forEach(sink));
     }
@@ -299,7 +324,16 @@
 
     @Override
     public OptionalDouble average() {
-        return collect(Collectors.toLongStatistics()).getMean();
+        long[] avg = collect(() -> new long[2],
+                             (ll, i) -> {
+                                 ll[0]++;
+                                 ll[1] += i;
+                             },
+                             (ll, rr) -> {
+                                 ll[0] += rr[0];
+                                 ll[1] += rr[1];
+                             });
+        return avg[0] > 0 ? OptionalDouble.of((double) avg[1] / avg[0]) : OptionalDouble.empty();
     }
 
     @Override
@@ -308,6 +342,11 @@
     }
 
     @Override
+    public LongStatistics statistics() {
+        return collect(LongStatistics::new, LongStatistics::accept, LongStatistics::combine);
+    }
+
+    @Override
     public long reduce(long identity, LongBinaryOperator op) {
         return pipeline(ReduceOps.makeLong(identity, op));
     }
@@ -323,25 +362,7 @@
             combiner.accept(left, right);
             return left;
         };
-        return collect(new Collectors.LongCollectorImpl<>(resultFactory, accumulator, operator, false));
-    }
-
-    @Override
-    public <R> R collect(Collector.OfLong<R> collector) {
-        return pipeline(ReduceOps.makeLong(collector));
-    }
-
-    @Override
-    public <R> R collectUnordered(Collector.OfLong<R> collector) {
-        if (collector.isConcurrent()) {
-            R container = collector.resultSupplier().get();
-            ObjLongConsumer<R> accumulator = collector.longAccumulator();
-            forEach(u -> accumulator.accept(container, u));
-            return container;
-        }
-        else {
-            return collect(collector);
-        }
+        return pipeline(ReduceOps.makeLong(resultFactory, accumulator, operator));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/stream/LongStatistics.java	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.stream;
+
+import java.util.StringJoiner;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * A state object for collecting statistics such as count, min, max, sum, and average for {@code long} values.
+ */
+public class LongStatistics implements LongConsumer, IntConsumer {
+    private long count;
+    private long sum;
+    private long min = Long.MAX_VALUE;
+    private long max = Long.MIN_VALUE;
+
+    @Override
+    public void accept(int value) {
+        accept((long) value);
+    }
+
+    @Override
+    public void accept(long value) {
+        ++count;
+        sum += value;
+        min = Math.min(min, value);
+        max = Math.max(max, value);
+    }
+
+    public void combine(LongStatistics other) {
+        count += other.count;
+        sum += other.sum;
+        min = Math.min(min, other.min);
+        max = Math.min(max, other.max);
+    }
+
+    public long getCount() {
+        return count;
+    }
+
+    public long getSum() {
+        return sum;
+    }
+
+    public long getMin() {
+        return min;
+    }
+
+    public long getMax() {
+        return max;
+    }
+
+    public double getMean() {
+        return count > 0 ? (double) sum / count : 0.0d;
+    }
+
+    @Override
+    public String toString() {
+        return new StringJoiner(", ", this.getClass().getSimpleName() + "{", "}")
+        .add("count=" + getCount())
+                .add("sum=" + getSum())
+                .add("min=" + getMin())
+                .add("max=" + getMax())
+                .toString();
+    }
+}
--- a/src/share/classes/java/util/stream/LongStream.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/LongStream.java	Mon Mar 18 22:09:50 2013 -0700
@@ -31,6 +31,8 @@
 import java.util.function.LongConsumer;
 import java.util.function.LongFunction;
 import java.util.function.LongPredicate;
+import java.util.function.LongToDoubleFunction;
+import java.util.function.LongToIntFunction;
 import java.util.function.LongUnaryOperator;
 import java.util.function.ObjIntConsumer;
 import java.util.function.ObjLongConsumer;
@@ -59,6 +61,10 @@
 
     <U> Stream<U> map(LongFunction<U> mapper);
 
+    IntStream map(LongToIntFunction mapper);
+
+    DoubleStream map(LongToDoubleFunction mapper);
+
     LongStream flatMap(LongFunction<? extends LongStream> mapper);
 
     LongStream flatMap(FlatMapper.OfLongToLong mapper);
@@ -89,10 +95,6 @@
                   ObjLongConsumer<R> accumulator,
                   BiConsumer<R, R> combiner);
 
-    <R> R collect(Collector.OfLong<R> collector);
-
-    <R> R collectUnordered(Collector.OfLong<R> collector);
-
     boolean anyMatch(LongPredicate predicate);
 
     boolean allMatch(LongPredicate predicate);
@@ -117,5 +119,7 @@
 
     long count();
 
+    LongStatistics statistics();
+
     long[] toArray();
 }
--- a/src/share/classes/java/util/stream/ReduceOps.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/ReduceOps.java	Mon Mar 18 22:09:50 2013 -0700
@@ -318,15 +318,17 @@
      * Constructs a {@code TerminalOp} that implements a mutable reduce on
      * {@code int} values
      *
-     * @param collector A {@code Collector} defining the reduction
+     * @param supplier
+     * @param accumulator
+     * @param combiner
      * @param <R> The type of the result
      * @return A {@code ReduceOp} implementing the reduction
      */
     public static <R> TerminalOp<Integer, R>
-    makeInt(Collector.OfInt<R> collector) {
-        Supplier<R> supplier = Objects.requireNonNull(collector).resultSupplier();
-        ObjIntConsumer<R> accumulator = collector.intAccumulator();
-        BinaryOperator<R> combiner = collector.combiner();
+    makeInt(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BinaryOperator<R> combiner) {
+        Objects.requireNonNull(supplier);
+        Objects.requireNonNull(accumulator);
+        Objects.requireNonNull(combiner);
         class ReducingSink extends Box<R> implements AccumulatingSink<Integer, R, ReducingSink>, Sink.OfInt {
             @Override
             public void begin(long size) {
@@ -446,15 +448,17 @@
      * Constructs a {@code TerminalOp} that implements a mutable reduce on
      * {@code long} values
      *
-     * @param collector A {@code Collector} defining the reduction
+     * @param supplier
+     * @param accumulator
+     * @param combiner
      * @param <R> The type of the result
      * @return A {@code TerminalOp} implementing the reduction
      */
     public static <R> TerminalOp<Long, R>
-    makeLong(Collector.OfLong<R> collector) {
-        Supplier<R> supplier = Objects.requireNonNull(collector).resultSupplier();
-        ObjLongConsumer<R> accumulator = collector.longAccumulator();
-        BinaryOperator<R> combiner = collector.combiner();
+    makeLong(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BinaryOperator<R> combiner) {
+        Objects.requireNonNull(supplier);
+        Objects.requireNonNull(accumulator);
+        Objects.requireNonNull(combiner);
         class ReducingSink extends Box<R> implements AccumulatingSink<Long, R, ReducingSink>, Sink.OfLong {
             @Override
             public void begin(long size) {
@@ -574,14 +578,17 @@
      * Constructs a {@code TerminalOp} that implements a mutable reduce on
      * {@code double} values
      *
-     * @param collector A {@code Collector} defining the reduction
+     * @param supplier
+     * @param accumulator
+     * @param combiner
      * @param <R> The type of the result
      * @return A {@code TerminalOp} implementing the reduction
      */
-    public static <R> TerminalOp<Double, R> makeDouble(Collector.OfDouble<R> collector) {
-        Supplier<R> supplier = Objects.requireNonNull(collector).resultSupplier();
-        ObjDoubleConsumer<R> accumulator = collector.doubleAccumulator();
-        BinaryOperator<R> combiner = collector.combiner();
+    public static <R> TerminalOp<Double, R>
+    makeDouble(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BinaryOperator<R> combiner) {
+        Objects.requireNonNull(supplier);
+        Objects.requireNonNull(accumulator);
+        Objects.requireNonNull(combiner);
         class ReducingSink extends Box<R> implements AccumulatingSink<Double, R, ReducingSink>, Sink.OfDouble {
             @Override
             public void begin(long size) {
--- a/src/share/classes/java/util/stream/package-info.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/src/share/classes/java/util/stream/package-info.java	Mon Mar 18 22:09:50 2013 -0700
@@ -244,7 +244,7 @@
  *
  * <p>(The primitive specializations of {@link java.util.stream.Stream}, such as {@link java.util.stream.IntStream},
  * even have convenience methods for common reductions, such as {@link java.util.stream.IntStream#sum()} or
- * {@link java.util.stream.IntStream#max()}, which are implemented as convenience wrappers around reduce.)
+ * {@link java.util.stream.IntStream#max()}, which are implemented as wrappers around reduce.)
  *
  * <p>Reduction parallellizes well since the implementation of {@code reduce} can operate on subsets of the
  * stream in parallel, and then combine the intermediate results to get the final correct answer.  Even if you were
@@ -328,7 +328,7 @@
  * </pre>
  * As with {@code reduce()}, the benefit of expressing {@collect} in this abstract way is that it is directly
  * amenable to parallelization: we can accumulate partial results in parallel and then combine them.  For example,
- * to collect the string representations of the elements in a stream accumulate them into an {@code ArrayList}, we
+ * to collect the string representations of the elements in a stream into an {@code ArrayList}, we
  * could write the obvious sequential for-each form:
  * <pre>
  *     ArrayList&lt;String> strings = new ArrayList&lt;>();
--- a/test-ng/README	Sun Mar 17 00:30:47 2013 +0800
+++ b/test-ng/README	Mon Mar 18 22:09:50 2013 -0700
@@ -5,7 +5,7 @@
    wget http://testng.org/testng-x.y.z.zip
    unzip testng-x.y.z.zip
    mkdir lib
-   cp testng-x.y.z/testng-x.y.z.jar lib
+   cp testng-x.y.z/testng.jar lib
 
    # run tests
    ant test
--- a/test-ng/TEST.ROOT	Sun Mar 17 00:30:47 2013 +0800
+++ b/test-ng/TEST.ROOT	Mon Mar 18 22:09:50 2013 -0700
@@ -1,4 +1,2 @@
 # This file identifies root(s) of the test-ng hierarchy.
 
-TestNG.dirs=tests
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/bootlib/TEST.properties	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,4 @@
+# This file identifies root(s) of the test-ng hierarchy.
+
+bootclasspath.dirs = . 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/boottests/TEST.properties	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,5 @@
+# This file identifies root(s) of the test-ng hierarchy.
+
+TestNG.dirs = .
+bootclasspath.dirs = .
+lib.dirs = /bootlib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/TEST.properties	Mon Mar 18 22:09:50 2013 -0700
@@ -0,0 +1,5 @@
+# This file identifies root(s) of the test-ng hierarchy.
+
+TestNG.dirs = .
+
+lib.dirs = /bootlib
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/ReduceByOpTest.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/ReduceByOpTest.java	Mon Mar 18 22:09:50 2013 -0700
@@ -30,16 +30,11 @@
 import java.util.stream.StreamTestDataProvider;
 import org.testng.annotations.Test;
 
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.function.Functions;
-import java.util.stream.Collector;
-import java.util.stream.Collectors;
 
 import static java.util.stream.Collectors.groupingBy;
-import static java.util.stream.Collectors.mapping;
 import static java.util.stream.Collectors.reducing;
 import static java.util.stream.LambdaTestHelpers.*;
 
@@ -63,7 +58,7 @@
 
         int uniqueSize = data.into(new HashSet<Integer>()).size();
         Map<Integer, List<Integer>> mgResult = exerciseTerminalOps(data, s -> s.collect(groupingBy(mId)));
-        Map<Integer, Integer> miResult = exerciseTerminalOps(data, s -> s.collect(groupingBy(mId, mapping(e -> 1, reducing(Integer::sum)))));
+        Map<Integer, Integer> miResult = exerciseTerminalOps(data, s -> s.collect(groupingBy(mId, reducing(e -> 1, Integer::sum))));
         assertEquals(miResult.keySet().size(), uniqueSize);
         for (Map.Entry<Integer, Integer> entry : miResult.entrySet())
             assertEquals((int) entry.getValue(), mgResult.get(entry.getKey()).size());
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/TabulatorsTest.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/TabulatorsTest.java	Mon Mar 18 22:09:50 2013 -0700
@@ -29,7 +29,9 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListMap;
@@ -50,7 +52,7 @@
 
 import static java.util.stream.Collectors.groupingBy;
 import static java.util.stream.Collectors.groupingByConcurrent;
-import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.partitioningBy;
 import static java.util.stream.Collectors.reducing;
 import static java.util.stream.Collectors.toCollection;
 import static java.util.stream.LambdaTestHelpers.assertContents;
@@ -65,7 +67,7 @@
 public class TabulatorsTest extends OpTestCase {
     // There are 8 versions of groupingBy:
     //   groupingBy: { map supplier, not } x { downstream collector, not } x { concurrent, not }
-    // There are 4 versions of partition { concurrent, not } x { map supplier, not }
+    // There are 2 versions of partition: { map supplier, not }
     // There are 4 versions of toMap
     //   mappedTo(function, mapSupplier?, mergeFunction?)
     // Each variety needs at least one test
@@ -109,24 +111,21 @@
         }
     }
 
-    static class PartitionAssertion<T> extends TabulationAssertion<T, Map<Boolean,T>> {
-        private final Class<? extends Map> clazz;
+    static class PartitionAssertion<T, D> extends TabulationAssertion<T, Map<Boolean,D>> {
         private final Predicate<T> predicate;
-        private final TabulationAssertion<T,T> downstream;
+        private final TabulationAssertion<T,D> downstream;
 
         protected PartitionAssertion(Predicate<T> predicate,
-                                     Class<? extends Map> clazz,
-                                     TabulationAssertion<T, T> downstream) {
-            this.clazz = clazz;
+                                     TabulationAssertion<T, D> downstream) {
             this.predicate = predicate;
             this.downstream = downstream;
         }
 
-        void assertValue(Map<Boolean, T> map,
+        void assertValue(Map<Boolean, D> map,
                          Supplier<Stream<T>> source,
                          boolean ordered) throws ReflectiveOperationException {
-            if (!clazz.isAssignableFrom(map.getClass()))
-                fail(String.format("Class mismatch in GroupedMapAssertion: %s, %s", clazz, map.getClass()));
+            if (!Map.class.isAssignableFrom(map.getClass()))
+                fail(String.format("Class mismatch in PartitionAssertion: %s", map.getClass()));
             assertEquals(2, map.size());
             downstream.assertValue(map.get(true), () -> source.get().filter(predicate), ordered);
             downstream.assertValue(map.get(false), () -> source.get().filter(predicate.negate()), ordered);
@@ -134,6 +133,23 @@
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
+    static class ListAssertion<T> extends TabulationAssertion<T, List<T>> {
+        @Override
+        void assertValue(List<T> value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+            if (!List.class.isAssignableFrom(value.getClass()))
+                fail(String.format("Class mismatch in ListAssertion: %s", value.getClass()));
+            Stream<T> stream = source.get();
+            List<T> result = new ArrayList<>();
+            for (Iterator<T> it = stream.iterator(); it.hasNext(); ) // avoid capturing result::add
+                result.add(it.next());
+            if (StreamOpFlagTestHelper.isStreamOrdered(stream) && ordered)
+                assertContents(value, result);
+            else
+                assertContentsUnordered(value, result);
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
     static class CollectionAssertion<T> extends TabulationAssertion<T, Collection<T>> {
         private final Class<? extends Collection> clazz;
         private final boolean targetOrdered;
@@ -169,7 +185,11 @@
 
         @Override
         void assertValue(U value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
-            assertEquals(value, source.get().map(mapper).reduce(reducer).get());
+            Optional<U> reduced = source.get().map(mapper).reduce(reducer);
+            if (value == null)
+                assertTrue(!reduced.isPresent());
+            else
+                assertEquals(value, reduced.get());
         }
     }
 
@@ -205,10 +225,9 @@
         Function<Integer, Integer> classifier = i -> i % 3;
 
         // Single-level groupBy
-        exerciseMapTabulation(data, groupingBy(classifier), new GroupedMapAssertion<>(classifier, HashMap.class,
-                                                                                      new CollectionAssertion<Integer>(ArrayList.class, true)));
+        exerciseMapTabulation(data, groupingBy(classifier), new GroupedMapAssertion<>(classifier, HashMap.class, new ListAssertion<>()));
         exerciseMapTabulation(data, groupingByConcurrent(classifier), new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class,
-                                                                                                new CollectionAssertion<Integer>(ArrayList.class, true)));
+                                                                                                new ListAssertion<>()));
 
         // With explicit constructors
         exerciseMapTabulation(data,
@@ -232,25 +251,25 @@
                               groupingBy(classifier, groupingBy(classifier2)),
                               new GroupedMapAssertion<>(classifier, HashMap.class,
                                                         new GroupedMapAssertion<>(classifier2, HashMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
         // with concurrent as upstream
         exerciseMapTabulation(data,
                               groupingByConcurrent(classifier, groupingBy(classifier2)),
                               new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class,
                                                         new GroupedMapAssertion<>(classifier2, HashMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
         // with concurrent as downstream
         exerciseMapTabulation(data,
                               groupingBy(classifier, groupingByConcurrent(classifier2)),
                               new GroupedMapAssertion<>(classifier, HashMap.class,
                                                         new GroupedMapAssertion<>(classifier2, ConcurrentHashMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
         // with concurrent as upstream and downstream
         exerciseMapTabulation(data,
                               groupingByConcurrent(classifier, groupingByConcurrent(classifier2)),
                               new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class,
                                                         new GroupedMapAssertion<>(classifier2, ConcurrentHashMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
 
         // With explicit constructors
         exerciseMapTabulation(data,
@@ -263,19 +282,19 @@
                               groupingByConcurrent(classifier, ConcurrentSkipListMap::new, groupingBy(classifier2, TreeMap::new)),
                               new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class,
                                                         new GroupedMapAssertion<>(classifier2, TreeMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
         // with concurrent as downstream
         exerciseMapTabulation(data,
                               groupingBy(classifier, TreeMap::new, groupingByConcurrent(classifier2, ConcurrentSkipListMap::new)),
                               new GroupedMapAssertion<>(classifier, TreeMap.class,
                                                         new GroupedMapAssertion<>(classifier2, ConcurrentSkipListMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
         // with concurrent as upstream and downstream
         exerciseMapTabulation(data,
                               groupingByConcurrent(classifier, ConcurrentSkipListMap::new, groupingByConcurrent(classifier2, ConcurrentSkipListMap::new)),
                               new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class,
                                                         new GroupedMapAssertion<>(classifier2, ConcurrentSkipListMap.class,
-                                                                                  new CollectionAssertion<Integer>(ArrayList.class, true))));
+                                                                                  new ListAssertion<>())));
     }
 
     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
@@ -306,24 +325,55 @@
 
         // Single-level map-reduce
         exerciseMapTabulation(data,
-                              groupingBy(classifier, mapping(mDoubler, reducing(Integer::sum))),
+                              groupingBy(classifier, reducing(mDoubler, Integer::sum)),
                               new GroupedMapAssertion<>(classifier, HashMap.class,
                                                         new ReduceAssertion<>(mDoubler, Integer::sum)));
         // with concurrent
         exerciseMapTabulation(data,
-                              groupingByConcurrent(classifier, mapping(mDoubler, reducing(Integer::sum))),
+                              groupingByConcurrent(classifier, reducing(mDoubler, Integer::sum)),
                               new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class,
                                                         new ReduceAssertion<>(mDoubler, Integer::sum)));
 
         // With explicit constructors
         exerciseMapTabulation(data,
-                              groupingBy(classifier, TreeMap::new, mapping(mDoubler, reducing(Integer::sum))),
+                              groupingBy(classifier, TreeMap::new, reducing(mDoubler, Integer::sum)),
                               new GroupedMapAssertion<>(classifier, TreeMap.class,
                                                         new ReduceAssertion<>(mDoubler, Integer::sum)));
         // with concurrent
         exerciseMapTabulation(data,
-                              groupingByConcurrent(classifier, ConcurrentSkipListMap::new, mapping(mDoubler, reducing(Integer::sum))),
+                              groupingByConcurrent(classifier, ConcurrentSkipListMap::new, reducing(mDoubler, Integer::sum)),
                               new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class,
                                                         new ReduceAssertion<>(mDoubler, Integer::sum)));
     }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testSimplePartition(String name, StreamTestData<Integer> data) throws ReflectiveOperationException {
+        Predicate<Integer> classifier = i -> i % 3 == 0;
+
+        // Single-level partition to downstream List
+        exerciseMapTabulation(data,
+                              partitioningBy(classifier),
+                              new PartitionAssertion<>(classifier, new ListAssertion<>()));
+        exerciseMapTabulation(data,
+                              partitioningBy(classifier, Collectors.toList()),
+                              new PartitionAssertion<>(classifier, new ListAssertion<>()));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testTwoLevelPartition(String name, StreamTestData<Integer> data) throws ReflectiveOperationException {
+        Predicate<Integer> classifier = i -> i % 3 == 0;
+        Predicate<Integer> classifier2 = i -> i % 7 == 0;
+
+        // Two level partition
+        exerciseMapTabulation(data,
+                              partitioningBy(classifier, partitioningBy(classifier2)),
+                              new PartitionAssertion<>(classifier,
+                                                       new PartitionAssertion(classifier2, new ListAssertion<>())));
+
+        // Two level partition with reduce
+        exerciseMapTabulation(data,
+                              partitioningBy(classifier, reducing(Integer::sum)),
+                              new PartitionAssertion<>(classifier,
+                                                       new ReduceAssertion<>(Functions.identity(), Integer::sum)));
+    }
 }
--- a/test/java/util/stream/Stream/EmployeeStreamTest.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/test/java/util/stream/Stream/EmployeeStreamTest.java	Mon Mar 18 22:09:50 2013 -0700
@@ -34,6 +34,7 @@
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiFunction;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Predicates;
 import java.util.stream.Collectors;
@@ -286,7 +287,7 @@
             ParallelType type = iter.next();
             Collection<Employee> l1 = generateData(DATA_SIZE);
             Collection<Employee> l2 = generateData(DATA_SIZE);
-           Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
             Employee limit = generateData();
             limit.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
             limit.age = rand.nextInt(Employee.MAX_AGE * 2);
@@ -380,32 +381,36 @@
 
             stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
                     .stream().sequential() : l.stream());
-            List<Employee> result2 = stream.filter(p1).filter(p2).collect(Collectors.<Employee>toList());
+            List<Employee> result2 = stream.filter(p1).filter(p2).collect(Collectors.toCollection(ArrayList<Employee>::new));
             stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
                     .stream().sequential() : l.stream());
-             List<Employee> result3 = stream.filter(Predicates.and(p1, p2)).collect(Collectors.<Employee>toList());
+            List<Employee> result3 = stream.filter(Predicates.and(p1, p2)).collect(Collectors.toCollection(ArrayList<Employee>::new));
             Collections.sort(result2, rule.getComparator());
             Collections.sort(result3, rule.getComparator());
             assertEquals(result2, result3);
-            result2.clear();
-            result3.clear();
 
+
+            //result2 could be a EmptyList, we're putting result2, result3 into
+            // concatList because EmptyList doesn't support addAll
+            List<Employee> concatList = new ArrayList<>();
             stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
                     .stream().sequential() : l.stream());
-            result2 = stream.filter(Predicates.and(p1, p2)).collect(Collectors.<Employee>toList());
+            result2 = stream.filter(Predicates.and(p1, p2)).collect(Collectors.toCollection(ArrayList<Employee>::new));
             stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
                     .stream().sequential() : l.stream());
-            result3 = stream.filter(Predicates.or(p1, p2)).collect(Collectors.<Employee>toList());
-            result2.addAll(result3);
+            result3 = stream.filter(Predicates.or(p1, p2)).collect(Collectors.toCollection(ArrayList<Employee>::new));
+            
+            concatList.addAll(result2);
+            concatList.addAll(result3);
             result3.clear();
             stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
                     .stream().sequential() : l.stream());
             Stream<Employee> stream2 = (type == ParallelType.Parallel) ? l.parallelStream()
                     : ((type == ParallelType.Sequential) ? l.stream().sequential() : l.stream());
-            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.<Employee>toList());
-            Collections.sort(result2, rule.getComparator());
+            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.toCollection(ArrayList<Employee>::new));
+            Collections.sort(concatList, rule.getComparator());
             Collections.sort(result3, rule.getComparator());
-            assertEquals(result2, result3);
+            assertEquals(concatList, result3);
 
             @SuppressWarnings("cast")
             Collection<Employee> emptyList = hasIni ? (Collection<Employee>) LambdaUtilities.create(typeObject,
@@ -464,6 +469,33 @@
     }
 
     @Test
+    public void testGroupBy() throws Throwable {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c =  generateData(DATA_SIZE);
+
+            Stream<Employee> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Map<Object, List<Employee>> result
+                    = stream.collect(Collectors.groupingBy(employeeGenericFunction(rule)));
+            verifyGroupBy(result, c, rule);
+
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyList = hasIni ?
+                    (Collection<Employee>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Employee>)LambdaUtilities.create(typeObject);
+            Stream<Employee> emptyStream = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                (type == ParallelType.Sequential) ? emptyList.stream().sequential() :
+                emptyList.stream();
+            assertTrue(emptyStream.collect(Collectors.groupingBy(employeeGenericFunction(rule))).isEmpty());
+        }
+    }
+
+    @Test
     @SuppressWarnings("unchecked")
     public void testLimit() throws Exception {
         Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
@@ -747,73 +779,48 @@
         return all;
     }
 
-    private void verifyGroupBy(Map<?, Collection<Employee>> result, boolean isFirst, Employee.Rule rule) {
+    private void verifyGroupBy(Map<Object, List<Employee>> result,
+            Collection<Employee> employees, Employee.Rule rule) {
+        Set<Employee> hashEm = new HashSet(employees);
         Iterator<?> keyiter = result.keySet().iterator();
         while (keyiter.hasNext()) {
-            Object obj = keyiter.next();
             switch (rule) {
             case AGE:
-                Integer key0 = (Integer) obj;
-                assertTrue(key0 < 10 && key0 >= 0);
-                Iterator<Employee> valueiter0 = result.get(key0).iterator();
-                while (valueiter0.hasNext()) {
-                    Employee i = valueiter0.next();
-                    if (isFirst)
-                        assertTrue(Integer.valueOf(Integer.toString(i.age).substring(0, 1)) == key0);
-                    else {
-                        String v = Integer.toString(i.age);
-                        int l = v.length();
-                        assertTrue(Integer.valueOf(v.substring(l - 1, l)) == key0);
-                    }
+                Integer ageKey = (Integer)keyiter.next();
+                List<Employee> ageEmList = result.get(ageKey);
+                for(Employee e: ageEmList) {
+                    assertEquals(e.age / 10, ageKey.intValue());
                 }
                 break;
             case SALARY:
-                Integer key1 = (Integer) obj;
-                assertTrue(key1 < 10 && key1 >= 0);
-                Iterator<Employee> valueiter1 = result.get(key1).iterator();
-                while (valueiter1.hasNext()) {
-                    Employee i = valueiter1.next();
-                    if (isFirst)
-                        assertTrue(Integer.valueOf(Float.toString(i.salary).substring(0, 1)) == key1);
-                    else {
-                        String v = Float.toString(i.salary);
-                        int len = v.length();
-                        assertTrue(Integer.valueOf(v.substring(len - 1, len)) == key1);
-                    }
+                String salaryKey = (String)keyiter.next();
+                List<Employee> salarayEmList = result.get(salaryKey);
+                for(Employee e: salarayEmList) {
+                    assertEquals(e.salary <= 6000 ? "LOW" : 
+                            (e.salary > 15000 ? "HIGH" : "MEDIUM"), salaryKey);
                 }
                 break;
             case MALE:
-                Boolean key2 = (Boolean) obj;
-                Iterator<Employee> valueiter2 = result.get(key2).iterator();
-                while (valueiter2.hasNext()) {
-                    Employee i = valueiter2.next();
-                    assertTrue(Boolean.valueOf(i.male) == key2);
+                Boolean genderKey = (Boolean)keyiter.next();
+                List<Employee> genderEmList = result.get(genderKey);
+                for(Employee e: genderEmList) {
+                    assertEquals(Boolean.valueOf(e.male), genderKey);
                 }
                 break;
             case TITLE:
-                Employee.Title key3 = (Employee.Title) obj;
-                Iterator<Employee> valueiter3 = result.get(key3).iterator();
-                while (valueiter3.hasNext()) {
-                    Employee i = valueiter3.next();
-                    assertTrue(i.title == key3);
+                Employee.Title titleKey = (Employee.Title)keyiter.next();
+                List<Employee> titleEmList = result.get(titleKey);
+                for(Employee e: titleEmList) {
+                    assertEquals(e.title, titleKey);
                 }
                 break;
             case ID:
+                Integer idKey = (Integer)keyiter.next();
+                List<Employee> idEmList = result.get(idKey);
+                for(Employee e: idEmList) {
+                    assertEquals(e.id.length(), idKey.intValue());
+                }
             default:
-                LambdaUtilities.CharType key4 = (LambdaUtilities.CharType) obj;
-                Iterator<Employee> valueiter4 = result.get(key4).iterator();
-                while (valueiter4.hasNext()) {
-                    Employee i = valueiter4.next();
-                    Character c = null;
-                    if (isFirst)
-                        c = Character.valueOf(i.id.charAt(0));
-                    else
-                        c = Character.valueOf(i.id.charAt(i.id.length() - 1));
-                    LambdaUtilities.CharType t = Character.isAlphabetic(c) ? (Character.isUpperCase(c) ? LambdaUtilities.CharType.UPPERCASE
-                            : LambdaUtilities.CharType.LOWERCASE)
-                            : (Character.isDigit(c) ? LambdaUtilities.CharType.DIGIT : LambdaUtilities.CharType.SPECIAL);
-                    assertTrue(t == key4);
-                }
                 break;
             }
         }
@@ -1062,4 +1069,22 @@
                 };
         }
     }
+    
+    
+    public static Function<Employee, Object> employeeGenericFunction(Employee.Rule rule) {
+        switch (rule) {
+            case AGE:
+                return e -> e.age / 10;
+            case SALARY:
+                return e -> e.salary <= 6000 ? "LOW" : (e.salary > 15000 ? "HIGH" : "MEDIUM");
+            case MALE:
+                return e -> e.male;
+            case TITLE:
+                return e -> e.title;
+            case ID:
+                return e -> e.id.length();
+            default:
+                throw new RuntimeException("No such rule");
+        }
+    }
 }
--- a/test/java/util/stream/Stream/IntegerStreamTest.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/test/java/util/stream/Stream/IntegerStreamTest.java	Mon Mar 18 22:09:50 2013 -0700
@@ -275,35 +275,35 @@
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            List<Integer> result2 = stream.filter(p1).filter(p2).collect(Collectors.<Integer>toList());
+            List<Integer> result2 = stream.filter(p1).filter(p2).collect(Collectors.toCollection(ArrayList<Integer>::new));
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            List<Integer> result3 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<Integer>toList());
+            List<Integer> result3 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.toCollection(ArrayList<Integer>::new));
             Comparator<Integer> c = (Comparator<Integer>)Comparators.naturalOrder();
             Collections.sort(result2, c);
             Collections.sort(result3, c);
             assertEquals(result2, result3);
-            result2.clear();
-            result3.clear();
 
+            //result2 could be a EmptyList, we're putting result2, result3 into
+            // concatList because EmptyList doesn't support addAll
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            result2 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<Integer>toList());
+            result2 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.toCollection(ArrayList<Integer>::new));
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            result3 = stream.filter(Predicates.or(p1,p2)).collect(Collectors.<Integer>toList());
+            result3 = stream.filter(Predicates.or(p1,p2)).collect(Collectors.toCollection(ArrayList<Integer>::new));
             result2.addAll(result3);
-            result3.clear();
+
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
             Stream<Integer>  stream2 = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.<Integer>toList());
+            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.toCollection(ArrayList<Integer>::new));
             Collections.sort(result2, c);
             Collections.sort(result3, c);
             assertEquals(result2, result3);
@@ -403,7 +403,7 @@
             Stream<Integer> stream = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            Map<Integer, Collection<Integer>> result
+            Map<Integer, List<Integer>> result
                     = stream.collect(Collectors.groupingBy(LambdaUtilities.posIntegerFunction(isHighest)));
             verifyGroupBy(result, isHighest);
 
@@ -972,7 +972,7 @@
         return all;
     }
 
-    private void verifyGroupBy(Map<Integer, Collection<Integer>> result, boolean isHighest){
+    private void verifyGroupBy(Map<Integer, List<Integer>> result, boolean isHighest){
         assertTrue(result.size() <= 10);
         Iterator<Integer> keyiter = result.keySet().iterator();
         while(keyiter.hasNext()) {
--- a/test/java/util/stream/Stream/StringBuilderStreamTest.java	Sun Mar 17 00:30:47 2013 +0800
+++ b/test/java/util/stream/Stream/StringBuilderStreamTest.java	Mon Mar 18 22:09:50 2013 -0700
@@ -46,7 +46,7 @@
 public class StringBuilderStreamTest<T extends Collection<StringBuilder>> implements ITest {
     private final static int MIN_LEN = 1 << 2;
 
-    private final static int MAX_LEN = 1 << 12;
+    private final static int MAX_LEN = 1 << 8;
 
     private final static int DATA_SIZE = 1 << 10;
 
@@ -324,25 +324,31 @@
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            List<StringBuilder> result2 = stream.filter(p1).filter(p2).collect(Collectors.<StringBuilder>toList());
+            List<StringBuilder> result2 = stream.filter(p1).filter(p2).collect(Collectors.toCollection(ArrayList<StringBuilder>::new));
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            List<StringBuilder> result3 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<StringBuilder>toList());
-            Collections.sort(result2, (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString()));
-            Collections.sort(result3, (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString()));
-            assertEquals(result2, result3);
-            result2.clear();
-            result3.clear();
+            List<StringBuilder> result3 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.toCollection(ArrayList<StringBuilder>::new));
+            
+            if(result2.isEmpty()) {
+                assertEquals(result2.size(), result3.size());
+            } else {
+                System.out.println(result2.getClass().getCanonicalName());
+                Collections.sort(result2, (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString()));
+                Collections.sort(result3, (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString()));
+                assertEquals(result2, result3);
+            }
 
+            //result2 could be a EmptyList, we're putting result2, result3 into
+            // concatList because EmptyList doesn't support addAll
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            result2 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<StringBuilder>toList());
+            result2 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.toCollection(ArrayList<StringBuilder>::new));
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            result3 = stream.filter(Predicates.or(p1,p2)).collect(Collectors.<StringBuilder>toList());
+            result3 = stream.filter(Predicates.or(p1,p2)).collect(Collectors.toCollection(ArrayList<StringBuilder>::new));
             result2.addAll(result3);
             result3.clear();
             stream = (type == ParallelType.Parallel) ? l.parallelStream():
@@ -351,7 +357,7 @@
             Stream<StringBuilder>  stream2 = (type == ParallelType.Parallel) ? l.parallelStream():
                     ((type == ParallelType.Sequential) ? l.stream().sequential() :
                     l.stream());
-            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.<StringBuilder>toList());
+            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.toCollection(ArrayList<StringBuilder>::new));
             Collections.sort(result2, NATRUAL_ORDER_CMP);
             Collections.sort(result3, NATRUAL_ORDER_CMP);
             assertEquals(result2, result3);
@@ -753,7 +759,7 @@
             Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            Map<LambdaUtilities.CharType, Collection<StringBuilder>> result
+            Map<LambdaUtilities.CharType, List<StringBuilder>> result
                     = stream.collect(Collectors.groupingBy(LambdaUtilities.sbGenericFunction(isFirst)));
             verifyGroupBy(result, isFirst);
 
@@ -817,7 +823,7 @@
         return all;
     }
 
-   private void verifyGroupBy(Map<LambdaUtilities.CharType, Collection<StringBuilder>> result, boolean isFirst){
+   private void verifyGroupBy(Map<LambdaUtilities.CharType, List<StringBuilder>> result, boolean isFirst){
         assertTrue(result.size() <= 4);
         Iterator<LambdaUtilities.CharType> keyiter = result.keySet().iterator();
         while(keyiter.hasNext()) {