changeset 6930:4cd29cf0c5ea

Eliminate Multifunction in favor of BiBlock in mapMulti call; move Multifunction.Collector to Stream.Downstream; rename Downstream.yield to send; rename mapMulti to explode
author briangoetz
date Thu, 10 Jan 2013 11:57:35 -0500
parents fcc817d42122
children dea58f434929
files src/share/classes/java/util/function/IntMultifunction.java src/share/classes/java/util/function/Multifunction.java src/share/classes/java/util/function/ObjIntBiBlock.java src/share/classes/java/util/stream/IntPipeline.java src/share/classes/java/util/stream/IntStream.java src/share/classes/java/util/stream/ReferencePipeline.java src/share/classes/java/util/stream/Stream.java test-ng/tests/org/openjdk/tests/java/util/LambdaTestHelpers.java test-ng/tests/org/openjdk/tests/java/util/stream/op/MultiMapOpTest.java test-ng/tests/org/openjdk/tests/java/util/stream/op/SpinedBufferTest.java test-ng/tests/org/openjdk/tests/java/util/stream/op/ToArrayOpTest.java test-ng/tests/org/openjdk/tests/java/util/stream/primitive/IntMultiMapOpTest.java
diffstat 12 files changed, 196 insertions(+), 179 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/function/IntMultifunction.java	Thu Jan 10 15:12:22 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * 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.function;
-
-import java.util.stream.IntStream;
-
-/**
- * A multi-valued function from int to int.  Multiple return is simulated
- * by yielding elements, arrays of elements, or streams of elements into a
- * Collector, which is passed as an additional argument to the multi-function.
- *
- * @author Brian Goetz
- */
-@FunctionalInterface
-public interface IntMultifunction {
-    public void apply(Downstream collector, int element);
-
-    /**
-     * 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 yielding an array containing
-     * [1, 2] is equivalent to yield(1); yield(2).
-     */
-    public interface Downstream {
-        void yield(int element);
-
-        default void yield(int[] array) {
-            for (int u : array)
-                yield(u);
-        }
-
-        default void yield(IntStream stream) {
-            stream.forEach(this::yield);
-        }
-    }
-}
--- a/src/share/classes/java/util/function/Multifunction.java	Thu Jan 10 15:12:22 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * 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.function;
-
-import java.util.Collection;
-import java.util.stream.Stream;
-
-/**
- * A multi-valued function from T to U.  Multiple return is simulated
- * by yielding elements, arrays of elements, collections of elements,
- * or streams of elements into a Collector, which is passed as an additional
- * argument to the multi-function.
- *
- * @author Brian Goetz
- */
-@FunctionalInterface
-public interface Multifunction<T,U> {
-    public void apply(Downstream<U> downstream, T element);
-
-    /** 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 yielding an array containing
-     * [1, 2] is equivalent to yield(1); yield(2).
-     */
-    public interface Downstream<U> {
-        void yield(U element);
-
-        default void yield(Collection<U> collection) {
-            for (U u : collection)
-                yield(u);
-        }
-
-        default void yield(U[] array) {
-            for (U u : array)
-                yield(u);
-        }
-
-        default void yield(Stream<U> stream) {
-            stream.forEach(this::yield);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/function/ObjIntBiBlock.java	Thu Jan 10 11:57:35 2013 -0500
@@ -0,0 +1,46 @@
+/*
+ * 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.function;
+
+/**
+ * An operation upon an (reference, int) pair value.  Unlike most other functional interfaces,
+ * {@code ObjIntBiBlock} is expected to operate via side-effects.
+ *
+ * <p>This is a primitive type specialization of {@link BiBlock} for
+ * {@code int}.
+ *
+ * @since 1.8
+ */
+public interface ObjIntBiBlock<T> {
+
+    /**
+     * Use the input values in an operation which may perform
+     * side-effects.
+     *
+     * @param t an input value
+     * @param i an input value
+     */
+    public void accept(T t, int i);
+}
--- a/src/share/classes/java/util/stream/IntPipeline.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/src/share/classes/java/util/stream/IntPipeline.java	Thu Jan 10 11:57:35 2013 -0500
@@ -95,17 +95,17 @@
     }
 
     @Override
-    public IntStream mapMulti(IntMultifunction mapper) {
-        Objects.requireNonNull(mapper);
+    public IntStream explode(ObjIntBiBlock<Downstream> exploder) {
+        Objects.requireNonNull(exploder);
         return pipeline(Ops.chainedInt(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
                                        new Ops.SinkWrapper<Integer>() {
                                            @Override
                                            public Sink<Integer> wrapSink(int flags, Sink sink) {
                                                return new Sink.ChainedInt(sink) {
-                                                   IntMultifunction.Downstream collector = downstream::accept;
+                                                   Downstream collector = downstream::accept;
 
                                                    public void accept(int t) {
-                                                       mapper.apply(collector, t);
+                                                       exploder.accept(collector, t);
                                                    }
                                                };
                                            }
--- a/src/share/classes/java/util/stream/IntStream.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/src/share/classes/java/util/stream/IntStream.java	Thu Jan 10 11:57:35 2013 -0500
@@ -52,7 +52,7 @@
 
     <U> Stream<U> map(ObjIntFunction<U> mapper);
 
-    IntStream mapMulti(IntMultifunction mapper);
+    IntStream explode(ObjIntBiBlock<Downstream> exploder);
 
     IntStream filter(IntPredicate predicate);
 
@@ -117,4 +117,23 @@
     }
 
     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);
+        }
+    }
 }
--- a/src/share/classes/java/util/stream/ReferencePipeline.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/src/share/classes/java/util/stream/ReferencePipeline.java	Thu Jan 10 11:57:35 2013 -0500
@@ -109,17 +109,17 @@
     }
 
     @Override
-    public <R> Stream<R> mapMulti(Multifunction<? super U, R> mapper) {
-        Objects.requireNonNull(mapper);
+    public <R> Stream<R> explode(BiBlock<Downstream<R>, ? super U> exploder) {
+        Objects.requireNonNull(exploder);
         return pipeline(Ops.<U,R>chainedRef(StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED,
                                             new Ops.SinkWrapper<U>() {
                                                 @Override
                                                 public Sink<U> wrapSink(int flags, Sink sink) {
                                                     return new Sink.ChainedReference<U>(sink) {
-                                                        Multifunction.Downstream<R> ds = downstream::accept;
+                                                        Downstream<R> ds = downstream::accept;
 
                                                         public void accept(U u) {
-                                                            mapper.apply(ds, u);
+                                                            exploder.accept(ds, u);
                                                         }
                                                     };
                                                 }
--- a/src/share/classes/java/util/stream/Stream.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/src/share/classes/java/util/stream/Stream.java	Thu Jan 10 11:57:35 2013 -0500
@@ -39,18 +39,43 @@
  */
 public interface Stream<T> extends BaseStream<T> {
 
+    /**
+     * Produce a {@code Stream} containing the elements of this stream that match
+     * the given {@link Predicate}.
+     */
     Stream<T> filter(Predicate<? super T> predicate);
 
+    /**
+     * Produce a {@code Stream} that is the result of applying the given {@link Function} to the
+     * elements of this stream.
+     */
     <R> Stream<R> map(Function<? super T, ? extends R> mapper);
 
+    /**
+     * Produce an {@link IntStream} that is the result of applying the given {@link IntFunction} to the
+     * elements of this stream.
+     */
     IntStream map(IntFunction<? super T> mapper);
 
-    <R> Stream<R> mapMulti(Multifunction<? super T, R> mapper);
+    /**
+     * 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 block; the block 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.
+     */
+    <R> Stream<R> explode(BiBlock<Downstream<R>, ? super T> exploder);
 
-    // @@@ flatMapToInt
-
+    /**
+     * Produce a {@code Stream} containing the elements of this stream that are distinct according to
+     * {@code Object.equals}.
+     * @return
+     */
     Stream<T> uniqueElements();
 
+    /**
+     * Produce a {@code Stream} containing the contents of this stream sorted by the provide {@link Comparator}.
+     */
     Stream<T> sorted(Comparator<? super T> comparator);
 
     /**
@@ -60,15 +85,24 @@
      */
     void forEach(Block<? super T> block);
 
+    /**
+     * Each element of this stream is processed by the provided block, until the
+     * termination criteria occurs.
+     *
+     * @param block the Block via which all elements will be processed.
+     */
     void forEachUntil(Block<? super T> block, BooleanSupplier until);
 
+    /**
+     * Produce a {@code Stream} containing the elements of this stream, and also provide elements
+     * to the specified {@link Block} as elements are passed through.
+     */
     Stream<T> tee(Block<? super T> block);
 
     /**
      * Limit this stream to at most {@code sizeLimit} elements. The stream will not be affected
      * if it contains less than or equal to {@code sizeLimit} elements.
      *
-     *
      * @param sizeLimit the number elements the stream should be limited to.
      * @return the truncated stream
      */
@@ -77,7 +111,6 @@
     /**
      * Skip at most {@code startIndex} elements.
      *
-     *
      * @param startIndex the number of elements to be skipped.
      * @return the truncated stream
      */
@@ -102,6 +135,11 @@
         @SuppressWarnings("unchecked")
         ObjIntFunction<T[]> generator = s -> (T[]) new Object[s];
         return toArray(generator);
+
+        /* @@@ We'd like to say:
+                return toArray(Object[]::new);
+           but the compiler crashes.
+         */
     }
 
     /**
@@ -145,8 +183,20 @@
 
     boolean noneMatch(Predicate<? super T> predicate);
 
+    /**
+     * Return an {@link Optional} describing the first element of the stream, or an
+     * empty {@code Optional} if the stream is empty
+     *
+     * @return
+     */
     Optional<T> findFirst();
 
+    /**
+     * Return an {@link Optional} describing some element of the stream, or an
+     * empty {@code Optional} if the stream is empty
+     *
+     * @return
+     */
     Optional<T> findAny();
 
     /**
@@ -156,6 +206,33 @@
      */
     Stream<T> sequential();
 
+    /**
+     * Convert this stream, if a sequential stream, to a parallel stream.
+     *
+     * @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/tests/org/openjdk/tests/java/util/LambdaTestHelpers.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/test-ng/tests/org/openjdk/tests/java/util/LambdaTestHelpers.java	Thu Jan 10 11:57:35 2013 -0500
@@ -50,9 +50,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 Multifunction<Integer, Integer> mfId = /*@@@ Sink::accept*/ (s,e) -> s.yield(e);
-    public static final Multifunction<Integer, Integer> mfNull = (s, e) -> { };
-    public static final Multifunction<Integer, Integer> mfLt = (s, e) -> { for (int i=0; i<e; i++) s.yield(i); };
+    public static final BiBlock<Stream.Downstream<Integer>, Integer> mfId = (s,e) -> s.send(e);
+    public static final BiBlock<Stream.Downstream<Integer>, Integer> mfNull = (s, e) -> { };
+    public static final BiBlock<Stream.Downstream<Integer>, Integer> mfLt = (s, e) -> { for (int i=0; i<e; i++) s.send(i); };
     public static final IntFunction<Integer> imDoubler = x -> x * 2;
     public static final LongFunction<Long> lmDoubler = x -> x * 2;
     public static final DoubleFunction<Double> dmDoubler = x -> x * 2;
@@ -84,12 +84,9 @@
 
     public static final ObjIntFunction<Object[]> objectArrayGenerator = s -> new Object[s];
 
-    public static final Multifunction<String, Character> flattenChars = new Multifunction<String, Character>() {
-        @Override
-        public void apply(Downstream<Character> sink, String element) {
-            for (int i=0; i<element.length(); i++) {
-                sink.yield(element.charAt(i));
-            }
+    public static final BiBlock<Stream.Downstream<Character>, String> flattenChars = (sink, element) -> {
+        for (int i=0; i<element.length(); i++) {
+            sink.send(element.charAt(i));
         }
     };
 
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/op/MultiMapOpTest.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/op/MultiMapOpTest.java	Thu Jan 10 11:57:35 2013 -0500
@@ -30,7 +30,7 @@
 import org.testng.annotations.Test;
 
 import java.util.Arrays;
-import java.util.function.Multifunction;
+import java.util.function.BiBlock;
 import java.util.stream.Stream;
 import java.util.stream.op.Node;
 
@@ -43,12 +43,12 @@
  */
 @Test
 public class MultiMapOpTest extends OpTestCase {
-    private static final Multifunction<Integer, Integer> mfIntToBits = (block, integer) -> {
+    private static final BiBlock<Stream.Downstream<Integer>, Integer> mfIntToBits = (block, integer) -> {
         int num = integer;
         for (int i = 0; i < 16 && num != 0; i++) {
             if ((num & (1 << i)) != 0) {
                 num &= ~(1 << i);
-                block.yield(i);
+                block.send(i);
             }
         }
     };
@@ -56,28 +56,28 @@
     public void testFlatMap() {
         String[] stringsArray = {"hello", "there", "", "yada"};
         Stream<String> strings = Arrays.asList(stringsArray).stream();
-        assertConcat(strings.mapMulti(flattenChars).iterator(), "hellothereyada");
+        assertConcat(strings.explode(flattenChars).iterator(), "hellothereyada");
 
-        assertCountSum(countTo(10).stream().mapMulti(mfId), 10, 55);
-        assertCountSum(countTo(10).stream().mapMulti(mfNull), 0, 0);
-        assertCountSum(countTo(3).stream().mapMulti(mfLt), 6, 4);
+        assertCountSum(countTo(10).stream().explode(mfId), 10, 55);
+        assertCountSum(countTo(10).stream().explode(mfNull), 0, 0);
+        assertCountSum(countTo(3).stream().explode(mfLt), 6, 4);
 
-        exerciseOps(new StreamTestData.ArrayData<>("stringsArray", stringsArray), s -> s.mapMulti(flattenChars));
-        exerciseOps(new StreamTestData.ArrayData<>("LONG_STRING", new String[]{LONG_STRING}), s -> s.mapMulti(flattenChars));
+        exerciseOps(new StreamTestData.ArrayData<>("stringsArray", stringsArray), s -> s.explode(flattenChars));
+        exerciseOps(new StreamTestData.ArrayData<>("LONG_STRING", new String[]{LONG_STRING}), s -> s.explode(flattenChars));
     }
 
     @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, StreamTestData<Integer> data) {
-        Node<Integer> result = exerciseOps(data, s -> s.mapMulti(mfId));
+        Node<Integer> result = exerciseOps(data, s -> s.explode(mfId));
         assertEquals(data.size(), result.count());
 
-        result = exerciseOps(data, s -> s.mapMulti(mfNull));
+        result = exerciseOps(data, s -> s.explode(mfNull));
         assertEquals(0, result.count());
 
-        result = exerciseOps(data, s -> s.mapMulti(mfId));
+        result = exerciseOps(data, s -> s.explode(mfId));
         assertEquals(result.count(), data.size());
 
-        exerciseOps(data, s -> s.mapMulti(mfLt));
-        exerciseOps(data, s -> s.mapMulti(mfIntToBits));
+        exerciseOps(data, s -> s.explode(mfLt));
+        exerciseOps(data, s -> s.explode(mfIntToBits));
     }
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/op/SpinedBufferTest.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/op/SpinedBufferTest.java	Thu Jan 10 11:57:35 2013 -0500
@@ -50,7 +50,7 @@
     // Create sizes around the boundary of spines
     List<Integer> sizes = Streams.intRange(0, 16).map(i -> 1 << i)
             .boxed()
-            .<Integer>mapMulti((s, i) -> { s.yield(i - 2); s.yield(i - 1); s.yield(i); s.yield(i + 1); s.yield(i + 2); })
+            .<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)
             .uniqueElements()
             .collect(Collectors.<Integer>toList());
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/op/ToArrayOpTest.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/op/ToArrayOpTest.java	Thu Jan 10 11:57:35 2013 -0500
@@ -32,7 +32,6 @@
 
 import java.util.*;
 import java.util.function.Function;
-import java.util.function.Multifunction;
 import java.util.stream.Stream;
 import java.util.stream.StreamOpFlag;
 import java.util.stream.Streams;
@@ -87,9 +86,9 @@
         // Double the size of the source
 
         Object[] objects = withData(data).
-                terminal(s -> s.mapMulti((Multifunction.Downstream<Integer> b, Integer e) -> {
-                    b.yield(e);
-                    b.yield(e);
+                terminal(s -> s.explode((Stream.Downstream<Integer> b, Integer e) -> {
+                    b.send(e);
+                    b.send(e);
                 }), s -> s.toArray()).
                 equalator(Arrays::equals).
                 exercise();
--- a/test-ng/tests/org/openjdk/tests/java/util/stream/primitive/IntMultiMapOpTest.java	Thu Jan 10 15:12:22 2013 +0100
+++ b/test-ng/tests/org/openjdk/tests/java/util/stream/primitive/IntMultiMapOpTest.java	Thu Jan 10 11:57:35 2013 -0500
@@ -27,7 +27,8 @@
 import org.openjdk.tests.java.util.stream.OpTestCase;
 import org.testng.annotations.Test;
 
-import java.util.function.IntMultifunction;
+import java.util.function.ObjIntBiBlock;
+import java.util.stream.IntStream;
 import java.util.stream.Streams;
 import java.util.stream.op.Node;
 
@@ -40,44 +41,44 @@
  */
 @Test
 public class IntMultiMapOpTest extends OpTestCase {
-    private static final IntMultifunction mfIntToBits = (c, integer) -> {
+    private static final ObjIntBiBlock<IntStream.Downstream> mfIntToBits = (c, integer) -> {
         int num = integer;
         for (int i = 0; i < 16 && num != 0; i++) {
             if ((num & (1 << i)) != 0) {
                 num &= ~(1 << i);
-                c.yield(i);
+                c.send(i);
             }
         }
     };
 
 
-    static final IntMultifunction idMapper = (c, e) -> c.yield(e);
+    static final ObjIntBiBlock<IntStream.Downstream> idMapper = (c, e) -> c.send(e);
 
-    static final IntMultifunction nullMapper = (c, e) -> {
+    static final ObjIntBiBlock<IntStream.Downstream> nullMapper = (c, e) -> {
     };
 
-    static final IntMultifunction rangeMapper = (c, e) -> {
-        for (int i = 0; i < e; i++) c.yield(i);
+    static final ObjIntBiBlock<IntStream.Downstream> rangeMapper = (c, e) -> {
+        for (int i = 0; i < e; i++) c.send(i);
     };
 
     public void testFlatMap() {
-        assertCountSum(Streams.intRange(1, 11).mapMulti(idMapper).boxed(), 10, 55);
-        assertCountSum(Streams.intRange(1, 11).mapMulti(nullMapper).boxed(), 0, 0);
-        assertCountSum(Streams.intRange(1, 4).mapMulti(rangeMapper).boxed(), 6, 4);
+        assertCountSum(Streams.intRange(1, 11).explode(idMapper).boxed(), 10, 55);
+        assertCountSum(Streams.intRange(1, 11).explode(nullMapper).boxed(), 0, 0);
+        assertCountSum(Streams.intRange(1, 4).explode(rangeMapper).boxed(), 6, 4);
     }
 
     @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
     public void testOps(String name, IntStreamTestData data) {
-        Node<Integer> result = exerciseOps(data, s -> s.mapMulti(idMapper));
+        Node<Integer> result = exerciseOps(data, s -> s.explode(idMapper));
         assertEquals(data.size(), result.count());
 
-        result = exerciseOps(data, s -> s.mapMulti(nullMapper));
+        result = exerciseOps(data, s -> s.explode(nullMapper));
         assertEquals(0, result.count());
 
-        result = exerciseOps(data, s -> s.mapMulti(idMapper));
+        result = exerciseOps(data, s -> s.explode(idMapper));
         assertEquals(result.count(), data.size());
 
-        exerciseOps(data, s -> s.mapMulti(rangeMapper));
-        exerciseOps(data, s -> s.mapMulti(mfIntToBits));
+        exerciseOps(data, s -> s.explode(rangeMapper));
+        exerciseOps(data, s -> s.explode(mfIntToBits));
     }
 }