changeset 5887:ba24de9416e3 it2-bootstrap

Merge
author briangoetz
date Fri, 31 Aug 2012 23:08:47 -0400
parents 4dd29128bc9b f94f4135cf68
children dc8c914e7cac
files test-ng/tests/org/openjdk/tests/java/util/LambdaTestHelpers.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/StreamOpTestCase.java
diffstat 14 files changed, 450 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/streams/LinearPipeline.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/LinearPipeline.java	Fri Aug 31 23:08:47 2012 -0400
@@ -90,8 +90,13 @@
     }
 
     @Override
-    public void forEach(Block<? super U> sink) {
-        pipeline(ForEachOp.make(sink));
+    public void forEach(Block<? super U> block) {
+        pipeline(ForEachOp.make(block));
+    }
+
+    @Override
+    public Stream<U> tee(Block<? super U> block) {
+        return chainLinear(new TeeOp<>(block));
     }
 
     @Override
--- a/src/share/classes/java/util/streams/MapPipeline.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/MapPipeline.java	Fri Aug 31 23:08:47 2012 -0400
@@ -68,10 +68,15 @@
     }
 
     @Override
-    public void forEach(BiBlock<K, V> sink) {
+    public void forEach(BiBlock<? super K, ? super V> sink) {
         pipeline(ForEachOp.make(sink));
     }
 
+    @Override
+    public MapStream<K, V> tee(BiBlock<? super K, ? super V> block) {
+        return chainMap(new BiTeeOp<>(block));
+    }
+
     public<U> U pipeline(TerminalOp<Mapping<K,V>, U> op) {
         return evaluate(op);
     }
--- a/src/share/classes/java/util/streams/MapStream.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/MapStream.java	Fri Aug 31 23:08:47 2012 -0400
@@ -38,7 +38,7 @@
 public interface MapStream<K, V> {
     MapIterator<K, V> iterator();
 
-    
+
     /**
      * Return the mapping which is semantically "first" in the stream. If the
      * stream is not ordered then repeated invocations may return a different
@@ -119,7 +119,14 @@
      *
      * @param sink the Sink via which all elements will be processed.
      */
-    void forEach(BiBlock<K, V> sink);
+    void forEach(BiBlock<? super K, ? super V> sink);
+
+    /**
+     * Each element of this stream is processed by the provided sink.
+     *
+     * @param block the Sink via which all elements will be processed.
+     */
+    MapStream<K, V> tee(BiBlock<? super K, ? super V> block);
 
     // @@@ Map, or MapFillable?
     <A extends Map<K, V>> A into(A target);
--- a/src/share/classes/java/util/streams/Sink.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/Sink.java	Fri Aug 31 23:08:47 2012 -0400
@@ -25,6 +25,7 @@
 package java.util.streams;
 
 import java.util.Mapping;
+import java.util.Objects;
 import java.util.functions.Block;
 
 /**
@@ -42,6 +43,7 @@
      * Sink is being reused by multiple calculations.
      * @param size The approximate size of the data to be pushed downstream, if
      * known or -1 if size is unknown.
+     * @@@ or something like that...
      */
     void begin(int size);
 
@@ -71,7 +73,7 @@
         protected final Sink downstream;
 
         public ChainedLinear(Sink downstream) {
-            this.downstream = downstream;
+            this.downstream = Objects.requireNonNull(downstream);
         }
 
         @Override
@@ -101,7 +103,7 @@
         protected final Sink downstream;
 
         public ChainedMap(Sink downstream) {
-            this.downstream = downstream;
+            this.downstream = Objects.requireNonNull(downstream);
         }
 
         @Override
--- a/src/share/classes/java/util/streams/Stream.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/Stream.java	Fri Aug 31 23:08:47 2012 -0400
@@ -101,6 +101,8 @@
 
     void forEach(Block<? super T> sink);
 
+    Stream<T> tee(Block<? super T> sink);
+
     <A extends Fillable<? super T>> A into(A target);
 
     Object[] toArray();
--- a/src/share/classes/java/util/streams/ops/BiMapOp.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/BiMapOp.java	Fri Aug 31 23:08:47 2012 -0400
@@ -61,7 +61,6 @@
     }
 
     public MapIterator<K, U> iterator(final MapIterator<K,V> source) {
-        Objects.requireNonNull(source);
         return iterator(source, mapper);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/streams/ops/BiTeeOp.java	Fri Aug 31 23:08:47 2012 -0400
@@ -0,0 +1,120 @@
+/*
+ * 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.streams.ops;
+
+import java.util.Iterator;
+import java.util.MapIterator;
+import java.util.Mapping;
+import java.util.Objects;
+import java.util.functions.BiBlock;
+import java.util.streams.Sink;
+import java.util.streams.Stream;
+
+/**
+ * Passes elements to provided block as encountered and passes objects
+ * downstream.
+ *
+ * @param <K> Type of element keys.
+ * @param <V> Type of element values.
+ */
+public class BiTeeOp<K, V> implements StatelessOp<Mapping<K,V>, Mapping<K,V>> {
+
+    /**
+     * Tee block for this operation.
+     */
+    public final BiBlock<? super K, ? super V> tee;
+
+    public BiTeeOp(BiBlock<? super K, ? super V> tee) {
+        this.tee = Objects.requireNonNull(tee);
+    }
+
+    @Override
+    public int getStreamFlags(int upstreamState) {
+        return upstreamState & ~(Stream.STATE_UNKNOWN_MASK_V1);
+    }
+
+    @Override
+    public Iterator<Mapping<K, V>> iterator(final Iterator<Mapping<K,V>> source) {
+        return iterator(source, tee);
+    }
+
+    public MapIterator<K, V> iterator(final MapIterator<K,V> source) {
+        return iterator(source, tee);
+    }
+
+    @Override
+    public Sink<Mapping<K, V>, K, V> sink(Sink sink) {
+        return new Sink.ChainedMap<K,V>(sink) {
+            @Override
+            public void accept(K k, V v) {
+                tee.apply(k,v);
+                downstream.accept(k, v);
+            }
+        };
+    }
+
+    public static <K, V> MapIterator<K, V> iterator(final Iterator<Mapping<K, V>> source,
+                                                    final BiBlock<? super K, ? super V> tee) {
+        Objects.requireNonNull(source);
+        Objects.requireNonNull(tee);
+        return new MapIterator<K, V>() {
+            Mapping<K, V> current;
+
+            @Override
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            @Override
+            public Mapping<K, V> next() {
+                current = source.next();
+
+                tee.apply(current.getKey(), current.getValue());
+
+                return current;
+            }
+
+            @Override
+            public K nextKey() {
+                return next().getKey();
+            }
+
+            @Override
+            public V nextValue() {
+                return next().getValue();
+            }
+
+            @Override
+            public K curKey() {
+                return current.getKey();
+            }
+
+            @Override
+            public V curValue() {
+                return current.getValue();
+            }
+        };
+    }
+}
--- a/src/share/classes/java/util/streams/ops/ForEachOp.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/ForEachOp.java	Fri Aug 31 23:08:47 2012 -0400
@@ -25,6 +25,7 @@
 package java.util.streams.ops;
 
 import java.util.Mapping;
+import java.util.Objects;
 import java.util.Spliterator;
 import java.util.concurrent.RecursiveAction;
 import java.util.functions.BiBlock;
@@ -41,7 +42,7 @@
     private final StatefulSink<T,Void> sink;
 
     protected ForEachOp(StatefulSink<T, Void> sink) {
-        this.sink = sink;
+        this.sink = Objects.requireNonNull(sink);
     }
 
     public static<T> ForEachOp<T> make(final Block<? super T> block) {
@@ -59,6 +60,7 @@
     }
 
     public static<K,V> ForEachOp<Mapping<K,V>> make(final BiBlock<? super K, ? super V> block) {
+        Objects.requireNonNull(block);
         return new ForEachOp<>(new StatefulSink<Mapping<K,V>, Void>() {
             @Override
             public void accept(Object k, Object v) {
--- a/src/share/classes/java/util/streams/ops/MapOp.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/MapOp.java	Fri Aug 31 23:08:47 2012 -0400
@@ -49,7 +49,6 @@
 
     @Override
     public Iterator<R> iterator(final Iterator<T> source) {
-        Objects.requireNonNull(source);
         return iterator(source, mapper);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/streams/ops/TeeOp.java	Fri Aug 31 23:08:47 2012 -0400
@@ -0,0 +1,81 @@
+/*
+ * 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.streams.ops;
+
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.functions.Block;
+import java.util.streams.Sink;
+import java.util.streams.Stream;
+
+/**
+ * TeeOp
+ */
+public class TeeOp<T> implements StatelessOp<T, T> {
+    public final Block<? super T> tee;
+
+    public TeeOp(Block<? super T> tee) {
+        this.tee = Objects.requireNonNull(tee);
+    }
+
+    @Override
+    public int getStreamFlags(int upstreamState) {
+        return upstreamState & ~Stream.STATE_UNKNOWN_MASK_V1;
+    }
+
+    @Override
+    public Iterator<T> iterator(final Iterator<T> source) {
+        return iterator(source, tee);
+    }
+
+    @Override
+    public Sink<T, ?, ?> sink(Sink sink) {
+        return new Sink.ChainedLinear<T>(sink) {
+            @Override
+            public void accept(T t) {
+                tee.apply(t);
+                downstream.accept(t);
+            }
+        };
+    }
+
+    public static<T> Iterator<T> iterator(final Iterator<T> source, final Block<? super T> tee) {
+        Objects.requireNonNull(source);
+        Objects.requireNonNull(tee);
+        return new Iterator<T>() {
+            @Override
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            @Override
+            public T next() {
+                T next = source.next();
+                tee.apply(next);
+                return next;
+            }
+        };
+    }
+}
--- a/test-ng/tests/org/openjdk/tests/java/util/LambdaTestHelpers.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/LambdaTestHelpers.java	Fri Aug 31 23:08:47 2012 -0400
@@ -185,23 +185,35 @@
         }
     }
 
-    public static<T> void assertContents(Iterable<T> pi, Iterable<T> list) {
-        assertContents(pi.iterator(), list.iterator());
+    public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected) {
+        assertContents(actual.iterator(), expected.iterator());
     }
 
-    public static<T> void assertContents(Iterator<T> pI, Iterator<T> lI) {
-        while (lI.hasNext()) {
-            assertTrue(pI.hasNext());
-            T pT = pI.next();
-            T lT = lI.next();
+    public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected) {
+        while (expected.hasNext()) {
+            assertTrue(actual.hasNext());
+            T pT = actual.next();
+            T lT = expected.next();
             assertEquals(pT, lT);
         }
-        assertTrue(!pI.hasNext());
+        assertTrue(!actual.hasNext());
     }
 
     @SafeVarargs
-    public static<T> void assertContents(Iterator<T> pi, T... values) {
-        assertContents(pi, Arrays.asList(values).iterator());
+    public static<T> void assertContents(Iterator<T> actual, T... expected) {
+        assertContents(actual, Arrays.asList(expected).iterator());
+    }
+
+    public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
+        ArrayList<T> one = new ArrayList<>();
+        for (T t : actual)
+            one.add(t);
+        ArrayList<T> two = new ArrayList<>();
+        for (T t : expected)
+            two.add(t);
+        Collections.sort(one);
+        Collections.sort(two);
+        assertContents(one, two);
     }
 
     static <T> void assertSplitContents(Iterable<Iterable<T>> splits, Iterable<T> list) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/MapStreamTestDataProvider.java	Fri Aug 31 23:08:47 2012 -0400
@@ -0,0 +1,103 @@
+/*
+ * 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 org.openjdk.tests.java.util.streams;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import org.testng.annotations.DataProvider;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+/**
+ * MapStreamTestDataProvider
+ * <p/>
+ */
+public class MapStreamTestDataProvider {
+
+    private static Map<Integer, Integer> makeIntegerIntegerMap(Class<? extends Map> type, int size) {
+        try {
+            Map<Integer, Integer> map = type.newInstance();
+            for (int i = 1; i <= size; i++) {
+                map.put(i, i);
+            }
+            return map;
+        } catch (InstantiationException | IllegalAccessException badNews) {
+            throw new Error(badNews);
+        }
+    }
+
+    private static Map<Integer, String> makeIntegerStringMap(Class<? extends Map> type, int size) {
+        try {
+            Map<Integer, String> map = type.newInstance();
+            for (int i = 1; i <= size; i++) {
+                map.put(i, Integer.toString(i));
+            }
+            return map;
+        } catch (InstantiationException | IllegalAccessException badNews) {
+            throw new Error(badNews);
+        }
+    }
+    private static final Class[] TYPES = {
+        HashMap.class,
+        Hashtable.class,
+        LinkedHashMap.class,
+        TreeMap.class,
+        ConcurrentHashMap.class,
+        ConcurrentSkipListMap.class
+    };
+    private static final int[] SIZES = {0, 1, 10, 100, 1000};
+    private static final Object[][] TEST_DATA;
+
+    static {
+        List<Object[]> list = new ArrayList<>();
+        for (Class type : TYPES) {
+            String name = type.getName();
+            for (int size : SIZES) {
+                String range = 0 == size ? "[empty]" : String.format("[1..%d]", size);
+
+                list.add(new Object[]{
+                            String.format("%s%s%s", name, "<Integer,Integer>", range),
+                            makeIntegerIntegerMap(type, size)
+                        });
+                list.add(new Object[]{
+                            String.format("%s%s%s", name, "<Integer,String>", range),
+                            makeIntegerStringMap(type, size)});
+            }
+        }
+        TEST_DATA = list.toArray(new Object[0][]);
+    }
+
+    // Return an array of ( String name, TestData<Integer> )
+    @DataProvider(name = "opMaps")
+    public static Object[][] makeMapTestData() {
+        return TEST_DATA;
+    }
+}
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/StreamOpTestCase.java	Fri Aug 31 22:42:01 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/StreamOpTestCase.java	Fri Aug 31 23:08:47 2012 -0400
@@ -325,7 +325,7 @@
         return sink;
     }
 
-    public static interface TestData<T> {
+    public static interface TestData<T> extends Iterable<T>, Traversable<T>, Sized {
         AbstractPipeline<?, T> seq();
         AbstractPipeline<?, T> par();
         Iterator<T> iterator();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/TeeOpTest.java	Fri Aug 31 23:08:47 2012 -0400
@@ -0,0 +1,92 @@
+/*
+ * 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 org.openjdk.tests.java.util.streams.ops;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.streams.StatefulSink;
+import org.testng.annotations.Test;
+
+import java.util.streams.ops.TeeOp;
+import java.util.streams.ops.ToArrayOp;
+import java.util.streams.ops.SeedlessFoldOp;
+import java.util.streams.ops.MapOp;
+
+import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
+
+
+import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
+
+/**
+ * TeeOpTest
+ *
+ */
+public class TeeOpTest extends StreamOpTestCase {
+    public void testRawIterator() {
+        StatefulSink<Integer,Object[]> copy = ToArrayOp.<Integer>singleton().sink();
+        copy.begin(-1);
+        assertCountSum(TeeOp.iterator(countTo(0).iterator(), copy), 0, 0);
+        copy.end();
+        assertCountSum(Arrays.asList(copy.getAndClearState()).iterator(), 0, 0);
+
+        copy.begin(-1);
+        assertCountSum(TeeOp.iterator(countTo(10).iterator(), copy), 10, 55);
+        copy.end();
+        assertCountSum(Arrays.asList(copy.getAndClearState()).iterator(), 10, 55);
+
+        copy.begin(-1);
+        assertCountSum(TeeOp.iterator(MapOp.iterator(countTo(10).iterator(), mDoubler), copy), 10, 110);
+        copy.end();
+        assertCountSum(Arrays.asList(copy.getAndClearState()).iterator(), 10, 110);
+    }
+
+    public void testTee() {
+        StatefulSink<Integer,Object[]> copy = ToArrayOp.<Integer>singleton().sink();
+        copy.begin(-1);
+        assertCountSum(countTo(0).stream().tee(copy), 0, 0);
+        copy.end();
+        assertCountSum(Arrays.asList(copy.getAndClearState()).iterator(), 0, 0);
+
+        copy.begin(-1);
+        assertCountSum(countTo(10).stream().tee(copy), 10, 55);
+        copy.end();
+        assertCountSum(Arrays.asList(copy.getAndClearState()).iterator(), 10, 55);
+
+        copy.begin(-1);
+        assertCountSum(countTo(10).stream().map(mDoubler).tee(copy), 10, 110);
+        copy.end();
+        assertCountSum(Arrays.asList(copy.getAndClearState()).iterator(), 10, 110);
+    }
+
+    @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
+    public void testOps(String name, TestData<Integer> data) {
+        StatefulSink<Integer,Optional<Integer>> fold = new SeedlessFoldOp<>(rPlus).sink();
+        fold.begin(-1);
+        StreamResult<Integer> result = exerciseOps(data, new TeeOp<>(fold));
+        assertContentsUnordered(result, data);
+
+        fold.end();
+    }
+}