changeset 7293:3aed6b4f4d42

Replace explode() with two forms of flatMap: flatMap(T->Stream<U>), and flatMap(FlatMapper<T,U>)
author briangoetz
date Thu, 07 Feb 2013 14:36:59 -0500
parents 1432662bd29c
children f23aa7677c34
files src/share/classes/java/util/stream/DoublePipeline.java src/share/classes/java/util/stream/DoubleStream.java src/share/classes/java/util/stream/FlatMapper.java src/share/classes/java/util/stream/IntPipeline.java src/share/classes/java/util/stream/IntStream.java src/share/classes/java/util/stream/LongPipeline.java src/share/classes/java/util/stream/LongStream.java src/share/classes/java/util/stream/ReferencePipeline.java src/share/classes/java/util/stream/Stream.java test-ng/bootlib/java/util/stream/LambdaTestHelpers.java test-ng/boottests/java/util/stream/SpinedBufferTest.java test-ng/tests/org/openjdk/tests/java/util/stream/ExplodeOpTest.java test-ng/tests/org/openjdk/tests/java/util/stream/ToArrayOpTest.java test/java/util/LambdaUtilities.java test/java/util/stream/Stream/EmployeeStreamTest.java test/java/util/stream/Stream/IntStreamTest.java test/java/util/stream/Stream/IntegerStreamTest.java test/java/util/stream/Stream/StringBuilderStreamTest.java test/java/util/stream/Streams/BasicTest.java
diffstat 19 files changed, 285 insertions(+), 260 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/DoublePipeline.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/DoublePipeline.java	Thu Feb 07 14:36:59 2013 -0500
@@ -33,7 +33,6 @@
 import java.util.function.DoubleFunction;
 import java.util.function.DoublePredicate;
 import java.util.function.DoubleUnaryOperator;
-import java.util.function.ObjDoubleConsumer;
 import java.util.function.Supplier;
 
 class DoublePipeline<E_IN> extends AbstractPipeline<E_IN, Double, DoubleStream> implements DoubleStream {
@@ -106,14 +105,12 @@
     }
 
     @Override
-    public DoubleStream explode(ObjDoubleConsumer<DoubleStream.Downstream> exploder) {
-        Objects.requireNonNull(exploder);
+    public DoubleStream flatMap(FlatMapper.OfDoubleToDouble mapper) {
+        Objects.requireNonNull(mapper);
         return pipeline(Ops.chainedDouble(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
                                           (flags, sink) -> new Sink.ChainedDouble(sink) {
-                                              Downstream collector = downstream::accept;
-
                                               public void accept(double t) {
-                                                  exploder.accept(collector, t);
+                                                  mapper.explodeInto(t, (Sink.OfDouble) downstream);
                                               }
                                           }));
     }
--- a/src/share/classes/java/util/stream/DoubleStream.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/DoubleStream.java	Thu Feb 07 14:36:59 2013 -0500
@@ -34,9 +34,6 @@
 import java.util.function.DoubleFunction;
 import java.util.function.DoublePredicate;
 import java.util.function.DoubleUnaryOperator;
-import java.util.function.ObjDoubleConsumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 public interface DoubleStream extends BaseStream<Double, DoubleStream> {
 
@@ -58,7 +55,11 @@
 
     <U> Stream<U> map(DoubleFunction<U> mapper);
 
-    DoubleStream explode(ObjDoubleConsumer<DoubleStream.Downstream> exploder);
+    default DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
+        return flatMap((double i, DoubleConsumer sink) -> mapper.apply(i).sequential().forEach(sink));
+    }
+
+    DoubleStream flatMap(FlatMapper.OfDoubleToDouble mapper);
 
     DoubleStream filter(DoublePredicate predicate);
 
@@ -105,7 +106,7 @@
     void forEachUntil(DoubleConsumer consumer, BooleanSupplier until);
 
     default double sum() {
-        // @@@ better algorithm to compensate for errors
+        // better algorithm to compensate for errors ?
         return reduce(0.0, Double::sum);
     }
 
@@ -123,25 +124,6 @@
 
     double[] toArray();
 
-    /**
-     * A collector for values associated with a given input.  Values can be
-     * yielded individually, or in aggregates such as collections, arrays, or
-     * streams; aggregates are flattened, so that sending  an array containing
-     * [1, 2] is equivalent to send(1); send(2).
-     */
-    interface Downstream {
-        void send(double element);
-
-        default void send(double[] array) {
-            for (double u : array)
-                send(u);
-        }
-
-        default void send(DoubleStream stream) {
-            stream.forEach(this::send);
-        }
-    }
-
     interface DoubleIterator extends Iterator<Double> {
 
         @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/stream/FlatMapper.java	Thu Feb 07 14:36:59 2013 -0500
@@ -0,0 +1,63 @@
+/*
+ * 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.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * FlatMapper
+ *
+ * @author Brian Goetz
+ */
+public interface FlatMapper<T, U> {
+    void explodeInto(T element, Consumer<U> sink);
+
+    interface ToInt<T> {
+        void explodeInto(T element, IntConsumer sink);
+    }
+
+    interface ToLong<T> {
+        void explodeInto(T element, LongConsumer sink);
+    }
+
+    interface ToDouble<T> {
+        void explodeInto(T element, DoubleConsumer sink);
+    }
+
+    interface OfIntToInt {
+        void explodeInto(int element, IntConsumer sink);
+    }
+
+    interface OfLongToLong {
+        void explodeInto(long element, LongConsumer sink);
+    }
+
+    interface OfDoubleToDouble {
+        void explodeInto(double element, DoubleConsumer sink);
+    }
+}
--- a/src/share/classes/java/util/stream/IntPipeline.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/IntPipeline.java	Thu Feb 07 14:36:59 2013 -0500
@@ -33,7 +33,6 @@
 import java.util.function.IntFunction;
 import java.util.function.IntPredicate;
 import java.util.function.IntUnaryOperator;
-import java.util.function.ObjIntConsumer;
 import java.util.function.Supplier;
 
 class IntPipeline<E_IN> extends AbstractPipeline<E_IN, Integer, IntStream> implements IntStream {
@@ -131,14 +130,12 @@
     }
 
     @Override
-    public IntStream explode(ObjIntConsumer<Downstream> exploder) {
-        Objects.requireNonNull(exploder);
+    public IntStream flatMap(FlatMapper.OfIntToInt mapper) {
+        Objects.requireNonNull(mapper);
         return pipeline(Ops.chainedInt(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
                                        (flags, sink) -> new Sink.ChainedInt(sink) {
-                                           Downstream collector = downstream::accept;
-
                                            public void accept(int t) {
-                                               exploder.accept(collector, t);
+                                               mapper.explodeInto(t, (Sink.OfInt) downstream);
                                            }
                                        }));
     }
--- a/src/share/classes/java/util/stream/IntStream.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/IntStream.java	Thu Feb 07 14:36:59 2013 -0500
@@ -35,7 +35,6 @@
 import java.util.function.IntFunction;
 import java.util.function.IntPredicate;
 import java.util.function.IntUnaryOperator;
-import java.util.function.ObjIntConsumer;
 
 public interface IntStream extends BaseStream<Integer, IntStream> {
 
@@ -61,7 +60,11 @@
 
     <U> Stream<U> map(IntFunction<U> mapper);
 
-    IntStream explode(ObjIntConsumer<Downstream> exploder);
+    default IntStream flatMap(IntFunction<? extends IntStream> mapper) {
+        return flatMap((int i, IntConsumer sink) -> mapper.apply(i).sequential().forEach(sink));
+    }
+
+    IntStream flatMap(FlatMapper.OfIntToInt mapper);
 
     IntStream filter(IntPredicate predicate);
 
@@ -125,25 +128,6 @@
 
     int[] toArray();
 
-    /**
-     * A collector for values associated with a given input.  Values can be
-     * yielded individually, or in aggregates such as collections, arrays, or
-     * streams; aggregates are flattened, so that sending  an array containing
-     * [1, 2] is equivalent to send(1); send(2).
-     */
-    interface Downstream {
-        void send(int element);
-
-        default void send(int[] array) {
-            for (int u : array)
-                send(u);
-        }
-
-        default void send(IntStream stream) {
-            stream.forEach(this::send);
-        }
-    }
-
     interface IntIterator extends Iterator<Integer> {
 
         @Override
--- a/src/share/classes/java/util/stream/LongPipeline.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/LongPipeline.java	Thu Feb 07 14:36:59 2013 -0500
@@ -33,7 +33,6 @@
 import java.util.function.LongFunction;
 import java.util.function.LongPredicate;
 import java.util.function.LongUnaryOperator;
-import java.util.function.ObjLongConsumer;
 import java.util.function.Supplier;
 
 class LongPipeline<E_IN> extends AbstractPipeline<E_IN, Long, LongStream> implements LongStream {
@@ -119,14 +118,12 @@
     }
 
     @Override
-    public LongStream explode(ObjLongConsumer<LongStream.Downstream> exploder) {
-        Objects.requireNonNull(exploder);
+    public LongStream flatMap(FlatMapper.OfLongToLong mapper) {
+        Objects.requireNonNull(mapper);
         return pipeline(Ops.chainedLong(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
                                         (flags, sink) -> new Sink.ChainedLong(sink) {
-                                            Downstream collector = downstream::accept;
-
                                             public void accept(long t) {
-                                                exploder.accept(collector, t);
+                                                mapper.explodeInto(t, (Sink.OfLong) downstream);
                                             }
                                         }));
     }
--- a/src/share/classes/java/util/stream/LongStream.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/LongStream.java	Thu Feb 07 14:36:59 2013 -0500
@@ -35,9 +35,6 @@
 import java.util.function.LongFunction;
 import java.util.function.LongPredicate;
 import java.util.function.LongUnaryOperator;
-import java.util.function.ObjLongConsumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 public interface LongStream extends BaseStream<Long, LongStream> {
 
@@ -61,7 +58,11 @@
 
     <U> Stream<U> map(LongFunction<U> mapper);
 
-    LongStream explode(ObjLongConsumer<LongStream.Downstream> exploder);
+    default LongStream flatMap(LongFunction<? extends LongStream> mapper) {
+        return flatMap((long i, LongConsumer sink) -> mapper.apply(i).sequential().forEach(sink));
+    }
+
+    LongStream flatMap(FlatMapper.OfLongToLong mapper);
 
     LongStream filter(LongPredicate predicate);
 
@@ -126,25 +127,6 @@
 
     long[] toArray();
 
-    /**
-     * A collector for values associated with a given input.  Values can be
-     * yielded individually, or in aggregates such as collections, arrays, or
-     * streams; aggregates are flattened, so that sending  an array containing
-     * [1, 2] is equivalent to send(1); send(2).
-     */
-    interface Downstream {
-        void send(long element);
-
-        default void send(long[] array) {
-            for (long u : array)
-                send(u);
-        }
-
-        default void send(LongStream stream) {
-            stream.forEach(this::send);
-        }
-    }
-
     interface LongIterator extends Iterator<Long> {
 
         @Override
--- a/src/share/classes/java/util/stream/ReferencePipeline.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/ReferencePipeline.java	Thu Feb 07 14:36:59 2013 -0500
@@ -149,19 +149,53 @@
     }
 
     @Override
-    public <R> Stream<R> explode(BiConsumer<Downstream<R>, ? super U> exploder) {
-        Objects.requireNonNull(exploder);
+    public <R> Stream<R> flatMap(FlatMapper<? super U, R> mapper) {
+        Objects.requireNonNull(mapper);
         return pipeline(Ops.<U,R>chainedRef(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
                                             (flags, sink) -> new Sink.ChainedReference<U>(sink) {
-                                                Downstream<R> ds = downstream::accept;
-
                                                 public void accept(U u) {
-                                                    exploder.accept(ds, u);
+                                                    mapper.explodeInto(u, downstream);
                                                 }
                                             }));
     }
 
     @Override
+    public IntStream flatMap(FlatMapper.ToInt<? super U> mapper) {
+        Objects.requireNonNull(mapper);
+        return pipeline(Ops.<U, Integer>chainedRef(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
+                                                   StreamShape.INT_VALUE,
+                                                   (flags, sink) -> new Sink.ChainedReference<U>(sink) {
+                                                       public void accept(U u) {
+                                                           mapper.explodeInto(u, (Sink.OfInt) downstream);
+                                                       }
+                                                   }));
+    }
+
+    @Override
+    public DoubleStream flatMap(FlatMapper.ToDouble<? super U> mapper) {
+        Objects.requireNonNull(mapper);
+        return pipeline(Ops.<U, Double>chainedRef(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
+                                                  StreamShape.DOUBLE_VALUE,
+                                                  (flags, sink) -> new Sink.ChainedReference<U>(sink) {
+                                                      public void accept(U u) {
+                                                          mapper.explodeInto(u, (Sink.OfDouble) downstream);
+                                                      }
+                                                  }));
+    }
+
+    @Override
+    public LongStream flatMap(FlatMapper.ToLong<? super U> mapper) {
+        Objects.requireNonNull(mapper);
+        return pipeline(Ops.<U, Long>chainedRef(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
+                                                StreamShape.LONG_VALUE,
+                                                (flags, sink) -> new Sink.ChainedReference<U>(sink) {
+                                                    public void accept(U u) {
+                                                        mapper.explodeInto(u, (Sink.OfLong) downstream);
+                                                    }
+                                                }));
+    }
+
+    @Override
     public Stream<U> distinct() {
         return pipeline(new UniqOp<U>());
     }
--- a/src/share/classes/java/util/stream/Stream.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/src/share/classes/java/util/stream/Stream.java	Thu Feb 07 14:36:59 2013 -0500
@@ -24,7 +24,6 @@
  */
 package java.util.stream;
 
-import java.util.Collection;
 import java.util.Comparator;
 import java.util.Comparators;
 import java.util.Optional;
@@ -86,11 +85,21 @@
     /**
      * Produce a {@code Stream} that is the result of mapping each element of this {@code Stream} to
      * zero or more elements.  The mapping is accomplished by passing the element, along with a
-     * {@link Downstream}, to a consumer; the consumer should call one of the {@code yield} methods on the
-     * {@code Downstream} to emit results into the new stream.  This method is sometimes called "flatMap"
-     * or "SelectMany" in other libraries.
+     * {@link Consumer}, to the provided {@link FlatMapper}; the {@code FlatMapper} should pass the emitted
+     * elements to the {@code Consumer}.
      */
-    <R> Stream<R> explode(BiConsumer<Stream.Downstream<R>, ? super T> exploder);
+    default <R> Stream<R> flatMap(Function<T, Stream<? extends R>> mapper) {
+        // We can do better than this, by polling cancellationRequested when stream is infinite
+        return flatMap((T t, Consumer<R> sink) -> mapper.apply(t).sequential().forEach(sink));
+    }
+
+    <R> Stream<R> flatMap(FlatMapper<? super T, R> mapper);
+
+    IntStream flatMap(FlatMapper.ToInt<? super T> mapper);
+
+    LongStream flatMap(FlatMapper.ToLong<? super T> mapper);
+
+    DoubleStream flatMap(FlatMapper.ToDouble<? super T> mapper);
 
     /**
      * Produce a {@code Stream} containing the elements of this stream that are distinct according to
@@ -245,27 +254,4 @@
      * @return a sequential stream.
      */
     Stream<T> parallel();
-
-    /** A collector for values associated with a given input.  Values can be
-     * yielded individually, or in aggregates such as collections, arrays, or
-     * streams; aggregates are flattened, so that sending an array containing
-     * [1, 2] is equivalent to send(1); send(2).
-     */
-    interface Downstream<U> {
-        void send(U element);
-
-        default void send(Collection<U> collection) {
-            for (U u : collection)
-                send(u);
-        }
-
-        default void send(U[] array) {
-            for (U u : array)
-                send(u);
-        }
-
-        default void send(Stream<U> stream) {
-            stream.forEach(this::send);
-        }
-    }
 }
--- a/test-ng/bootlib/java/util/stream/LambdaTestHelpers.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test-ng/bootlib/java/util/stream/LambdaTestHelpers.java	Thu Feb 07 14:36:59 2013 -0500
@@ -69,9 +69,9 @@
     public static final Function<Integer, Integer> mZero = x -> 0;
     public static final Function<Integer, Integer> mId = x -> x;
     public static final Function<Integer, Integer> mDoubler = x -> x * 2;
-    public static final BiConsumer<java.util.stream.Stream.Downstream<Integer>, Integer> mfId = (s,e) -> s.send(e);
-    public static final BiConsumer<java.util.stream.Stream.Downstream<Integer>, Integer> mfNull = (s, e) -> { };
-    public static final BiConsumer<java.util.stream.Stream.Downstream<Integer>, Integer> mfLt = (s, e) -> { for (int i=0; i<e; i++) s.send(i); };
+    public static final FlatMapper<Integer, Integer> mfId = (e, s) -> s.accept(e);
+    public static final FlatMapper<Integer, Integer> mfNull = (e, s) -> { };
+    public static final FlatMapper<Integer, Integer> mfLt = (e, s) -> { for (int i=0; i<e; i++) s.accept(i); };
     public static final ToIntFunction<Integer> imDoubler = x -> x * 2;
     public static final ToLongFunction<Long> lmDoubler = x -> x * 2;
     public static final ToDoubleFunction<Double> dmDoubler = x -> x * 2;
@@ -111,9 +111,15 @@
 
     public static final IntFunction<Object[]> objectArrayGenerator = s -> new Object[s];
 
-    public static final BiConsumer<java.util.stream.Stream.Downstream<Character>, String> flattenChars = (sink, element) -> {
-        for (int i=0; i<element.length(); i++) {
-            sink.send(element.charAt(i));
+    public static final FlatMapper<String, Character> flattenChars = (String string, Consumer<Character> sink) -> {
+        for (int i=0; i<string.length(); i++) {
+            sink.accept(string.charAt(i));
+        }
+    };
+
+    public static final FlatMapper.ToInt<String> flattenInt = (String string, IntConsumer sink) -> {
+        for (int i=0; i<string.length(); i++) {
+            sink.accept((int) string.charAt(i));
         }
     };
 
--- a/test-ng/boottests/java/util/stream/SpinedBufferTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test-ng/boottests/java/util/stream/SpinedBufferTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -39,18 +39,19 @@
 public class SpinedBufferTest {
 
     // Create sizes around the boundary of spines
-    List<Integer> sizes = Streams.intRange(0, 16).map(i -> 1 << i)
-            .boxed()
-            .<Integer>explode((s, i) -> {
-                s.send(i - 2);
-                s.send(i - 1);
-                s.send(i);
-                s.send(i + 1);
-                s.send(i + 2);
-            })
-            .filter(i -> i >= 0)
-            .distinct()
-            .collect(Collectors.toList());
+    List<Integer> sizes = Streams.intRange(0, 16)
+                                 .map(i -> 1 << i)
+                                 .flatMap((i, s) -> {
+                                     s.accept(i - 2);
+                                     s.accept(i - 1);
+                                     s.accept(i);
+                                     s.accept(i + 1);
+                                     s.accept(i + 2);
+                                 })
+                                 .filter(i -> i >= 0)
+                                 .boxed()
+                                 .distinct()
+                                 .collect(Collectors.toList());
 
     // SpinedBuffer
 
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/ExplodeOpTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/ExplodeOpTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -41,87 +41,86 @@
 @Test
 public class ExplodeOpTest extends OpTestCase {
 
-    static final BiConsumer<Stream.Downstream<Integer>, Integer> integerRangeMapper = (c, e) -> {
-        for (int i = 0; i < e; i++) c.send(i);
+    static final FlatMapper<Integer, Integer> integerRangeMapper = (e, c) -> {
+        for (int i = 0; i < e; i++) c.accept(i);
     };
 
     public void testFlatMap() {
         String[] stringsArray = {"hello", "there", "", "yada"};
         Stream<String> strings = Arrays.asList(stringsArray).stream();
-        assertConcat(strings.explode(flattenChars).iterator(), "hellothereyada");
+        assertConcat(strings.flatMap(flattenChars).iterator(), "hellothereyada");
 
-        assertCountSum(countTo(10).stream().explode(mfId), 10, 55);
-        assertCountSum(countTo(10).stream().explode(mfNull), 0, 0);
-        assertCountSum(countTo(3).stream().explode(mfLt), 6, 4);
+        assertCountSum(countTo(10).stream().flatMap(mfId), 10, 55);
+        assertCountSum(countTo(10).stream().flatMap(mfNull), 0, 0);
+        assertCountSum(countTo(3).stream().flatMap(mfLt), 6, 4);
 
-        exerciseOps(new StreamTestData.ArrayData<>("stringsArray", stringsArray), s -> s.explode(flattenChars));
-        exerciseOps(new StreamTestData.ArrayData<>("LONG_STRING", new String[]{LONG_STRING}), s -> s.explode(flattenChars));
+        exerciseOps(new StreamTestData.ArrayData<>("stringsArray", stringsArray), s -> s.flatMap(flattenChars));
+        exerciseOps(new StreamTestData.ArrayData<>("LONG_STRING", new String[]{LONG_STRING}), s -> s.flatMap(flattenChars));
     }
 
     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, StreamTestData<Integer> data) {
-        Collection<Integer> result = exerciseOps(data, s -> s.explode(mfId));
+        Collection<Integer> result = exerciseOps(data, s -> s.flatMap(mfId));
         assertEquals(data.size(), result.size());
 
-        result = exerciseOps(data, s -> s.explode(mfNull));
+        result = exerciseOps(data, s -> s.flatMap(mfNull));
         assertEquals(0, result.size());
 
-        exerciseOps(data, s -> s.explode(mfLt));
+        exerciseOps(data, s -> s.flatMap(mfLt));
 
-        exerciseOps(data, s -> s.explode(integerRangeMapper));
+        exerciseOps(data, s -> s.flatMap(integerRangeMapper));
 
-        exerciseOps(data, s -> s.explode((Stream.Downstream<Integer> c, Integer e) -> c.send(Streams.intRange(0, e).boxed().limit(10))));
+        exerciseOps(data, s -> s.flatMap((Integer e) -> Streams.intRange(0, e).boxed().limit(10)));
     }
 
     //
 
     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
     public void testIntOps(String name, IntStreamTestData data) {
-        Collection<Integer> result = exerciseOps(data, s -> s.explode((c, e) -> c.send(e)));
+        Collection<Integer> result = exerciseOps(data, s -> s.flatMap((i, sink) -> sink.accept(i)));
         assertEquals(data.size(), result.size());
 
-        result = exerciseOps(data, s -> s.explode((c, e) -> { }));
+        result = exerciseOps(data, s -> s.flatMap((i, sink) -> { }));
         assertEquals(0, result.size());
 
-        exerciseOps(data, s -> s.explode((c, e) -> {
-            for (int i = 0; i < e; i++) c.send(i);
+        exerciseOps(data, s -> s.flatMap((e, sink) -> {
+            for (int i = 0; i < e; i++) sink.accept(i);
         }));
 
-        exerciseOps(data, s -> s.explode((c, e) -> c.send(Streams.intRange(0, e).limit(10))));
+        exerciseOps(data, s -> s.flatMap(e -> Streams.intRange(0, e).limit(10)));
     }
 
     //
 
     @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
     public void testLongOps(String name, LongStreamTestData data) {
-        Collection<Long> result = exerciseOps(data, s -> s.explode((c, e) -> c.send(e)));
+        Collection<Long> result = exerciseOps(data, s -> s.flatMap((i, sink) -> sink.accept(i)));
         assertEquals(data.size(), result.size());
 
-        result = exerciseOps(data, s -> s.explode((c, e) -> { }));
+        result = exerciseOps(data, s -> s.flatMap((i, sink) -> { }));
         assertEquals(0, result.size());
 
-        exerciseOps(data, s -> s.explode((c, e) -> {
-            for (long i = 0; i < e; i++) c.send(i);
+        exerciseOps(data, s -> s.flatMap((e, sink) -> {
+            for (int i = 0; i < e; i++) sink.accept(i);
         }));
 
-        exerciseOps(data, s -> s.explode((c, e) -> c.send(Streams.longRange(0, e).limit(10))));
+        exerciseOps(data, s -> s.flatMap(e -> Streams.longRange(0, e).limit(10)));
     }
 
     //
 
     @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
     public void testDoubleOps(String name, DoubleStreamTestData data) {
-        Collection<Double> result = exerciseOps(data, s -> s.explode((c, e) -> c.send(e)));
+        Collection<Double> result = exerciseOps(data, s -> s.flatMap((i, sink) -> sink.accept(i)));
         assertEquals(data.size(), result.size());
 
-        result = exerciseOps(data, s -> s.explode((c, e) -> { }));
+        result = exerciseOps(data, s -> s.flatMap((i, sink) -> { }));
         assertEquals(0, result.size());
 
-        exerciseOps(data, s -> s.explode((c, e) -> {
-            for (long i = 0; i < e; i++) c.send(i);
+        exerciseOps(data, s -> s.flatMap((e, sink) -> {
+            for (int i = 0; i < e; i++) sink.accept(i);
         }));
 
-        exerciseOps(data, s -> s.explode((c, e) -> c.send(Streams.longRange(0, (long)e).doubles().limit(10))));
+        exerciseOps(data, s -> s.flatMap(e -> Streams.longRange(0, (long) e).doubles().limit(10)));
     }
-
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/ToArrayOpTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/ToArrayOpTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -27,6 +27,7 @@
 import org.testng.annotations.Test;
 
 import java.util.*;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.*;
 
@@ -74,9 +75,9 @@
         // Fixed size optimizations will not be used
 
         Object[] objects = exerciseTerminalOps(data,
-                                               s -> s.explode((Stream.Downstream<Integer> b, Integer e) -> {
-                                                   b.send(e);
-                                                   b.send(e);
+                                               s -> s.flatMap((Integer e, Consumer<Integer> sink) -> {
+                                                   sink.accept(e);
+                                                   sink.accept(e);
                                                }),
                                                s -> s.toArray());
         assertTrue(objects.length == data.size() * 2);
@@ -194,9 +195,9 @@
         // Fixed size optimizations will not be used
 
         int[] objects = exerciseTerminalOps(data,
-                                               s -> s.explode((b, e) -> {
-                                                   b.send(e);
-                                                   b.send(e);
+                                               s -> s.flatMap((e, sink) -> {
+                                                   sink.accept(e);
+                                                   sink.accept(e);
                                                }),
                                                s -> s.toArray());
         assertTrue(objects.length == data.size() * 2);
@@ -270,9 +271,9 @@
         // Fixed size optimizations will not be used
 
         long[] objects = exerciseTerminalOps(data,
-                                               s -> s.explode((b, e) -> {
-                                                   b.send(e);
-                                                   b.send(e);
+                                               s -> s.flatMap((e, sink) -> {
+                                                   sink.accept(e);
+                                                   sink.accept(e);
                                                }),
                                                s -> s.toArray());
         assertTrue(objects.length == data.size() * 2);
@@ -346,9 +347,9 @@
         // Fixed size optimizations will not be used
 
         double[] objects = exerciseTerminalOps(data,
-                                               s -> s.explode((b, e) -> {
-                                                   b.send(e);
-                                                   b.send(e);
+                                               s -> s.flatMap((e, sink) -> {
+                                                   sink.accept(e);
+                                                   sink.accept(e);
                                                }),
                                                s -> s.toArray());
         assertTrue(objects.length == data.size() * 2);
--- a/test/java/util/LambdaUtilities.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test/java/util/LambdaUtilities.java	Thu Feb 07 14:36:59 2013 -0500
@@ -38,6 +38,7 @@
 import java.util.function.*;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
+import java.util.stream.FlatMapper;
 
 public class LambdaUtilities {
 
@@ -120,88 +121,84 @@
         return c -> Character.isDigit(c);
     }
 
-    public static BiConsumer<Stream.Downstream<Integer>, Integer> genIntegerFlatBiConsumer(int selected) {
+    public static FlatMapper<Integer, Integer> genIntegerFlatMapper(int selected) {
         switch (selected) {
             case 0:
                 //Generate a empty collection
-                return ( s, e ) -> { };
+                return ( e, s ) -> { };
             case 1:
-                return ( s, e ) -> { s.send(e);
-            }
-            ;
+                return ( e, s ) -> { s.accept(e); };
             case 2:
                 //Generate a triangle has different value
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < e; i++) {
-                        s.send(e * (e - 1) / 2 + i);
+                        s.accept(e * (e - 1) / 2 + i);
                     }
                 };
             case 3:
                 //Generate a triangle has different value
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < e; i++) {
-                        s.send(e);
+                        s.accept(e);
                     }
                 };
             default:
                 //Generate 64 folded flat map
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < 1 << 6; i++) {
-                        s.send(e);
+                        s.accept(e);
                     }
                 };
         }
     }
 
-    public static ObjIntConsumer<IntStream.Downstream> genFlatIntConsumer(int selected) {
+    public static FlatMapper.OfIntToInt genIntFlatMapper(int selected) {
         switch (selected) {
             case 0:
                 //Generate a empty collection
-                return ( s, e ) -> { };
+                return ( e, s ) -> { };
             case 1:
-                return ( s, e ) -> { s.send(e);
-            }
-            ;
+                return ( e, s ) -> { s.accept(e); };
             case 2:
                 //Generate a triangle has different value
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < e; i++) {
-                        s.send(e * (e - 1) / 2 + i);
+                        s.accept(e * (e - 1) / 2 + i);
                     }
                 };
             case 3:
                 //Generate a triangle has different value
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < e; i++) {
-                        s.send(e);
+                        s.accept(e);
                     }
                 };
             default:
                 //Generate 64 folded flat map
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < 1 << 6; i++) {
-                        s.send(e);
+                        s.accept(e);
                     }
                 };
         }
     }
 
-    public static BiConsumer<Stream.Downstream<StringBuilder>, StringBuilder> genSBFlatBiConsumer(int selected, int unit) {
+    public static FlatMapper<StringBuilder, StringBuilder> genSBFlatMapper(int selected, int unit) {
         switch(selected) {
             case 0:
                 //Generate a empty collection
-                return (s, e) -> { };
-            case 1: return (s, e) -> { s.send(e); };
+                return (e, s) -> { };
+            case 1: return (e, s) -> { s.accept(e); };
             case 2:
-                return (s, e) -> {int step = e.length() / unit + unit -1;
+                return (e, s) -> {int step = e.length() / unit + unit -1;
                                     for (int i = 0; i < e.length(); i += step)
-                                        s.send(new StringBuilder(e.substring(i, i + step >= e.length() ?
-                                                e.length() - 1 : i + step)));};
+                                        s.accept(new StringBuilder(e.substring(i, i + step >= e.length() ?
+                                                                                  e.length() - 1 : i + step)));};
             case 3:
             default:
                 //Generate 64 folded flat map
-                return (s, e) -> {int step = e.length() / unit + unit -1;
-                                    for (int i = 0; i < e.length(); i+=step) s.send(e);};
+                return (e, s) -> {int step = e.length() / unit + unit -1;
+                                    for (int i = 0; i < e.length(); i+=step) s.accept(e);};
         }
     }
 
--- a/test/java/util/stream/Stream/EmployeeStreamTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test/java/util/stream/Stream/EmployeeStreamTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -33,11 +33,11 @@
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Predicate;
 import java.util.function.Predicates;
 import java.util.stream.Collectors;
+import java.util.stream.FlatMapper;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
 import static org.testng.Assert.*;
@@ -474,11 +474,11 @@
            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
             Stream<Employee> stream1 = (type == ParallelType.Parallel) ? col.parallelStream()
                     : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
-            List<Employee> result1 = stream1.explode(genEmployeeFlatBiConsumer(2, rule)).collect(Collectors.<Employee>toList());
+            List<Employee> result1 = stream1.flatMap(genEmployeeFlatMapper(2, rule)).collect(Collectors.<Employee>toList());
 
             Stream<Employee> stream2 = (type == ParallelType.Parallel) ? col.parallelStream()
                     : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
-            List<Employee> result2 = stream2.explode(genEmployeeFlatBiConsumer(2, rule)).limit(limit)
+            List<Employee> result2 = stream2.flatMap(genEmployeeFlatMapper(2, rule)).limit(limit)
                     .collect(Collectors.<Employee>toList());
 
             if (col instanceof Set) {
@@ -694,7 +694,7 @@
             Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
             Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
                     : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
-            List<Employee> list2 = stream1.explode(genEmployeeFlatBiConsumer(4, rule)).distinct().collect(Collectors.<Employee>toList());
+            List<Employee> list2 = stream1.flatMap(genEmployeeFlatMapper(4, rule)).distinct().collect(Collectors.<Employee>toList());
             assertEquals(set1.size(), list2.size());
             assertTrue(set1.containsAll(list2));
         }
@@ -999,65 +999,65 @@
 
     }
 
-    public static BiConsumer<Stream.Downstream<Employee>, Employee>
-            genEmployeeFlatBiConsumer(int selected, Employee.Rule rule) {
+    public static FlatMapper<Employee, Employee>
+    genEmployeeFlatMapper(int selected, Employee.Rule rule) {
         switch (selected) {
             case 0:
                 //Generate a empty collection
-                return ( s, e ) -> { };
+                return ( e, s ) -> { };
             case 1:
-                return ( s, e ) -> { s.send(e); };
+                return ( e, s ) -> { s.accept(e); };
             case 2:
                 switch (rule) {
                 case AGE:
-                    return ( s, e ) -> {
+                    return ( e, s ) -> {
                         for (int i = 0; i < e.age; i+= e.age / 10) {
                             Employee employee = e.clone();
                             employee.id = e.id;
                             employee.age = e.age * (e.age - 1) / 2 + i;
-                            s.send(employee);
+                            s.accept(employee);
                         }
                     };
                 case SALARY:
-                    return ( s, e ) -> {
+                    return ( e, s ) -> {
                         for (int i = 0; i < (int)e.salary; i+= (int)e.salary / 10) {
                             Employee employee = e.clone();
                             employee.id = e.id;
                             employee.salary = e.salary * (e.salary - 1) / 2 + i;
-                            s.send(employee);
+                            s.accept(employee);
                         }
                     };
                 case MALE:
-                    return (s, e) -> {
+                    return ( e, s ) -> {
                           Employee employee = e.clone();
                           employee.male = !e.male;
                           employee.id = e.id;
-                          s.send(employee);
+                          s.accept(employee);
                     };
                 case TITLE:
-                    return (s, e) -> {
+                    return ( e, s ) -> {
                         for (int i = 0; i < e.title.ordinal(); i ++) {
                             Employee employee = e.clone();
                             employee.title = Employee.Title.values()[i];
                             employee.id = e.id;
-                            s.send(employee);
+                            s.accept(employee);
                         }
                     };
                 case ID:
                 default:
-                    return (s, e) -> {
+                    return ( e, s ) -> {
                         for (int i = 0; i < e.id.length(); i += 2) {
                             Employee employee = e.clone();
                             employee.id = e.id;
-                            s.send(employee);
+                            s.accept(employee);
                         }
                     };
                 }
             case 3:
             default:
-                return ( s, e ) -> {
+                return ( e, s ) -> {
                     for (int i = 0; i < 10; i++) {
-                        s.send(e);
+                        s.accept(e);
                     }
                 };
         }
--- a/test/java/util/stream/Stream/IntStreamTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test/java/util/stream/Stream/IntStreamTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -341,8 +341,8 @@
                     : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
                     Arrays.stream(array);
             int limit = rand.nextInt(ARRAY_SIZE * (ARRAY_SIZE - 1));
-            int[] flatArr = stream1.explode(LambdaUtilities.genFlatIntConsumer(2)).toArray();
-            int[] result= stream2.explode(LambdaUtilities.genFlatIntConsumer(2)).limit(limit).toArray();
+            int[] flatArr = stream1.flatMap(LambdaUtilities.genIntFlatMapper(2)).toArray();
+            int[] result= stream2.flatMap(LambdaUtilities.genIntFlatMapper(2)).limit(limit).toArray();
             if(limit > flatArr.length)
                 assertEquals(flatArr.length,result.length);
             else {
@@ -363,7 +363,7 @@
                     : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
                     Arrays.stream(array);
             int selected = rand.nextInt(5);
-            int[] flatArray = stream.explode(LambdaUtilities.genFlatIntConsumer(selected)).sorted().toArray();
+            int[] flatArray = stream.flatMap(LambdaUtilities.genIntFlatMapper(selected)).sorted().toArray();
             verifyMultifunction(array, flatArray, selected);
         }
     }
@@ -667,13 +667,13 @@
             IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array1)
                     : (p == ParallelType.Sequential) ? Arrays.stream(array1).sequential() :
                     Arrays.stream(array1);
-            int[] toArray1 = stream.explode(LambdaUtilities.genFlatIntConsumer(4)).distinct().toArray();
+            int[] toArray1 = stream.flatMap(LambdaUtilities.genIntFlatMapper(4)).distinct().toArray();
             assertEquals(toArray1, array1);
 
             IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0]):
                     (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
                     Arrays.stream(new int[0]);
-            assertEquals(emptyStream.explode(LambdaUtilities.genFlatIntConsumer(4)).distinct().toArray().length, 0);
+            assertEquals(emptyStream.flatMap(LambdaUtilities.genIntFlatMapper(4)).distinct().toArray().length, 0);
         }
     }
 
--- a/test/java/util/stream/Stream/IntegerStreamTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test/java/util/stream/Stream/IntegerStreamTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -38,6 +38,7 @@
 import java.util.function.Predicate;
 import java.util.function.Predicates;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import java.util.stream.Streams;
 import static org.testng.Assert.*;
@@ -375,21 +376,19 @@
     @Test
     @SuppressWarnings("unchecked")
     public void testForEachUntil() throws Exception{
-        Iterator<ParallelType> iter
-                = EnumSet.allOf(ParallelType.class).iterator();
-        while(iter.hasNext()) {
-            ParallelType type = iter.next();
-            Collection<Integer> c =  generateData(START, END);
-            final int limit = rand.nextInt(c.size());
-            final Collection<Integer> cLimit =  hasIni ?
-                    LambdaUtilities.create(typeObject, initSize) :
-                    LambdaUtilities.create(typeObject);
-            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
-                    (type == ParallelType.Sequential) ? c.stream().sequential() :
-                    c.stream();
-            stream1.forEachUntil(t -> cLimit.add(t), () -> cLimit.size() == limit);
-            assertEquals(cLimit.size(), limit);
-        }
+        // @@@ BG This test is not well suited to parallel execution, because there is a race between checking
+        // the size and adding another element.  So it has been downgrade to sequential-only
+        ParallelType type = ParallelType.Sequential;
+        Collection<Integer> c =  generateData(START, END);
+        final int limit = rand.nextInt(c.size());
+        final Collection<Integer> cLimit =  hasIni ?
+                                            LambdaUtilities.create(typeObject, initSize) :
+                                            LambdaUtilities.create(typeObject);
+        Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                                  (type == ParallelType.Sequential) ? c.stream().sequential() :
+                                  c.stream();
+        stream1.forEachUntil(t -> cLimit.add(t), () -> cLimit.size() == limit);
+        assertEquals(cLimit.size(), limit);
     }
 
     @Test
@@ -438,12 +437,12 @@
             Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            Collection<Integer> result1 = stream1.explode(LambdaUtilities.genIntegerFlatBiConsumer(2)).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            Collection<Integer> result1 = stream1.flatMap(LambdaUtilities.genIntegerFlatMapper(2)).collect(Collectors.toCollection(LinkedList<Integer>::new));
 
             Stream<Integer> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            Collection<Integer> result2 = stream2.explode(LambdaUtilities.genIntegerFlatBiConsumer(2)).limit(limit).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            Collection<Integer> result2 = stream2.flatMap(LambdaUtilities.genIntegerFlatMapper(2)).limit(limit).collect(Collectors.toCollection(LinkedList<Integer>::new));
 
             if(limit > result1.size())
                 assertEquals(result1.size(), result2.size());
@@ -471,7 +470,7 @@
             Stream<Integer> stream = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            List<Integer> result = stream.explode(LambdaUtilities.genIntegerFlatBiConsumer(selected)).collect(Collectors.<Integer>toList());
+            List<Integer> result = stream.flatMap(LambdaUtilities.genIntegerFlatMapper(selected)).collect(Collectors.<Integer>toList());
             verifyMultifunction(c, result, selected);
         }
     }
@@ -519,7 +518,7 @@
             Stream<Integer> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            PrimitiveIterator.OfInt pit = stream2.map(LambdaUtilities.opToIntFunction(op, randOps)).iterator();
+            IntStream.IntIterator pit = stream2.map(LambdaUtilities.opToIntFunction(op, randOps)).iterator();
             verifyAfterOps(c.iterator(), pit, op, randOps);
         }
     }
@@ -933,7 +932,7 @@
             Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
                     (type == ParallelType.Sequential) ? c1.stream().sequential() :
                     c1.stream();
-            List<Integer> list2 = stream1.explode(LambdaUtilities.genIntegerFlatBiConsumer(4)).distinct().collect(Collectors.<Integer>toList());
+            List<Integer> list2 = stream1.flatMap(LambdaUtilities.genIntegerFlatMapper(4)).distinct().collect(Collectors.<Integer>toList());
             assertEquals(set1.size(), list2.size());
             assertTrue(set1.containsAll(list2));
         }
@@ -1120,7 +1119,7 @@
 
     }
 
-    private void verifyAfterOps(Iterator<Integer> itOrg, PrimitiveIterator.OfInt pit, LambdaUtilities.IntOp op,
+    private void verifyAfterOps(Iterator<Integer> itOrg, IntStream.IntIterator pit, LambdaUtilities.IntOp op,
             int value) {
         while(itOrg.hasNext() && pit.hasNext()) {
             int expected = itOrg.next();
--- a/test/java/util/stream/Stream/StringBuilderStreamTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test/java/util/stream/Stream/StringBuilderStreamTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -378,12 +378,12 @@
             Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            Collection<StringBuilder> result1  = stream1.explode(LambdaUtilities.genSBFlatBiConsumer(2, DATA_SIZE / 10)).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            Collection<StringBuilder> result1  = stream1.flatMap(LambdaUtilities.genSBFlatMapper(2, DATA_SIZE / 10)).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
 
             Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            Collection<StringBuilder> result2 = stream2.explode(LambdaUtilities.genSBFlatBiConsumer(2, DATA_SIZE / 10)).limit(limit).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            Collection<StringBuilder> result2 = stream2.flatMap(LambdaUtilities.genSBFlatMapper(2, DATA_SIZE / 10)).limit(limit).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
 
             if(limit > result1.size())
                 assertTrue(result1.size() == result2.size());
@@ -404,7 +404,7 @@
             Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? c.parallelStream():
                     (type == ParallelType.Sequential) ? c.stream().sequential() :
                     c.stream();
-            List<StringBuilder> result = stream.explode(LambdaUtilities.genSBFlatBiConsumer(selected, DATA_SIZE / 10)).collect(Collectors.<StringBuilder>toList());
+            List<StringBuilder> result = stream.flatMap(LambdaUtilities.genSBFlatMapper(selected, DATA_SIZE / 10)).collect(Collectors.<StringBuilder>toList());
             verifyFlatBiBlock(c, result, selected, DATA_SIZE / 10);
         }
     }
@@ -735,7 +735,7 @@
             Set<StringBuilder> set1 = new HashSet<>(c1);
             Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
                     : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
-             List<StringBuilder> list2 = stream1.explode(LambdaUtilities.genSBFlatBiConsumer(3, DATA_SIZE / 10)).distinct().collect(Collectors.<StringBuilder>toList());
+             List<StringBuilder> list2 = stream1.flatMap(LambdaUtilities.genSBFlatMapper(3, DATA_SIZE / 10)).distinct().collect(Collectors.<StringBuilder>toList());
             assertEquals(set1.size(), list2.size());
             assertTrue(set1.containsAll(list2));
         }
--- a/test/java/util/stream/Streams/BasicTest.java	Thu Feb 07 09:46:08 2013 -0800
+++ b/test/java/util/stream/Streams/BasicTest.java	Thu Feb 07 14:36:59 2013 -0500
@@ -72,14 +72,14 @@
         final int randomValue = rand.nextInt();
         final int randomSize= rand.nextInt(Integer.MAX_VALUE);
         IntStream is = Streams.generateInt(() -> randomValue);
-        assertEquals(is.spliterator().exactSizeIfKnown(), -1);
+        assertEquals(is.spliterator().getExactSizeIfKnown(), -1);
 
         IntStream is1 = Streams.generateInt(() -> randomValue);
         IntStream is2 = Streams.generateInt(() -> randomValue);
         assertEquals(is1.limit(randomSize).max(), is2.limit(randomSize).min());
 
         Stream<String> ss = Streams.generate(() -> HELLO_WORLD);
-        assertEquals(ss.spliterator().exactSizeIfKnown(), -1);
+        assertEquals(ss.spliterator().getExactSizeIfKnown(), -1);
         Stream<String> ss1 = Streams.generate(() -> HELLO_WORLD);
         Stream<String> ss2 = Streams.generate(() -> HELLO_WORLD);
         assertEquals(ss1.limit(randomSize).findAny(), ss2.limit(randomSize).findAny());