# HG changeset patch # User tvaleev # Date 1461974277 25200 # Node ID 1258d14cf2cc846a721020bb8ad6f11ff8badca9 # Parent 45cd7cc65382d660fca5657e1111acf8546fbaa6 8153293: Preserve SORTED and DISTINCT characteristics for boxed() and asLongStream() operations Reviewed-by: psandoz diff -r 45cd7cc65382 -r 1258d14cf2cc jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java --- a/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java Sat Apr 30 00:30:31 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java Fri Apr 29 16:57:57 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -167,6 +167,19 @@ return Nodes.doubleBuilder(exactSizeIfKnown); } + private Stream mapToObj(DoubleFunction mapper, int opFlags) { + return new ReferencePipeline.StatelessOp(this, StreamShape.DOUBLE_VALUE, opFlags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return new Sink.ChainedDouble(sink) { + @Override + public void accept(double t) { + downstream.accept(mapper.apply(t)); + } + }; + } + }; + } // DoubleStream @@ -184,7 +197,7 @@ @Override public final Stream boxed() { - return mapToObj(Double::valueOf); + return mapToObj(Double::valueOf, 0); } @Override @@ -207,18 +220,7 @@ @Override public final Stream mapToObj(DoubleFunction mapper) { Objects.requireNonNull(mapper); - return new ReferencePipeline.StatelessOp(this, StreamShape.DOUBLE_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { - @Override - Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { - @Override - public void accept(double t) { - downstream.accept(mapper.apply(t)); - } - }; - } - }; + return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT); } @Override diff -r 45cd7cc65382 -r 1258d14cf2cc jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java --- a/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java Sat Apr 30 00:30:31 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java Fri Apr 29 16:57:57 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -170,6 +170,19 @@ return Nodes.intBuilder(exactSizeIfKnown); } + private Stream mapToObj(IntFunction mapper, int opFlags) { + return new ReferencePipeline.StatelessOp(this, StreamShape.INT_VALUE, opFlags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return new Sink.ChainedInt(sink) { + @Override + public void accept(int t) { + downstream.accept(mapper.apply(t)); + } + }; + } + }; + } // IntStream @@ -187,8 +200,7 @@ @Override public final LongStream asLongStream() { - return new LongPipeline.StatelessOp(this, StreamShape.INT_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { + return new LongPipeline.StatelessOp(this, StreamShape.INT_VALUE, 0) { @Override Sink opWrapSink(int flags, Sink sink) { return new Sink.ChainedInt(sink) { @@ -203,8 +215,7 @@ @Override public final DoubleStream asDoubleStream() { - return new DoublePipeline.StatelessOp(this, StreamShape.INT_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { + return new DoublePipeline.StatelessOp(this, StreamShape.INT_VALUE, 0) { @Override Sink opWrapSink(int flags, Sink sink) { return new Sink.ChainedInt(sink) { @@ -219,7 +230,7 @@ @Override public final Stream boxed() { - return mapToObj(Integer::valueOf); + return mapToObj(Integer::valueOf, 0); } @Override @@ -242,18 +253,7 @@ @Override public final Stream mapToObj(IntFunction mapper) { Objects.requireNonNull(mapper); - return new ReferencePipeline.StatelessOp(this, StreamShape.INT_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { - @Override - Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { - @Override - public void accept(int t) { - downstream.accept(mapper.apply(t)); - } - }; - } - }; + return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT); } @Override diff -r 45cd7cc65382 -r 1258d14cf2cc jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java --- a/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java Sat Apr 30 00:30:31 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java Fri Apr 29 16:57:57 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -167,6 +167,19 @@ return Nodes.longBuilder(exactSizeIfKnown); } + private Stream mapToObj(LongFunction mapper, int opFlags) { + return new ReferencePipeline.StatelessOp(this, StreamShape.LONG_VALUE, opFlags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return new Sink.ChainedLong(sink) { + @Override + public void accept(long t) { + downstream.accept(mapper.apply(t)); + } + }; + } + }; + } // LongStream @@ -184,8 +197,7 @@ @Override public final DoubleStream asDoubleStream() { - return new DoublePipeline.StatelessOp(this, StreamShape.LONG_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { + return new DoublePipeline.StatelessOp(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { return new Sink.ChainedLong(sink) { @@ -200,7 +212,7 @@ @Override public final Stream boxed() { - return mapToObj(Long::valueOf); + return mapToObj(Long::valueOf, 0); } @Override @@ -223,18 +235,7 @@ @Override public final Stream mapToObj(LongFunction mapper) { Objects.requireNonNull(mapper); - return new ReferencePipeline.StatelessOp(this, StreamShape.LONG_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { - @Override - Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { - @Override - public void accept(long t) { - downstream.accept(mapper.apply(t)); - } - }; - } - }; + return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT); } @Override diff -r 45cd7cc65382 -r 1258d14cf2cc jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java Sat Apr 30 00:30:31 2016 +0100 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java Fri Apr 29 16:57:57 2016 -0700 @@ -27,11 +27,18 @@ import java.util.Arrays; import java.util.Random; +import java.util.Spliterator; import java.util.stream.DoubleStream; import java.util.stream.LongStream; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +/** + * @test + * @bug 8153293 + */ @Test public class DoublePrimitiveOpsTests { @@ -42,6 +49,13 @@ assertEquals(sum, 1.0 + 2.0 + 3.0 + 4.0 + 5.0); } + public void testFlags() { + assertTrue(LongStream.range(1, 10).asDoubleStream().boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(DoubleStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + } + public void testToArray() { { double[] array = LongStream.range(1, 10).asDoubleStream().map(i -> i * 2).toArray(); @@ -72,6 +86,22 @@ } } + public void testSortDistinct() { + { + double[] range = LongStream.range(0, 10).asDoubleStream().toArray(); + + assertEquals(LongStream.range(0, 10).asDoubleStream().sorted().distinct().toArray(), range); + assertEquals(LongStream.range(0, 10).asDoubleStream().parallel().sorted().distinct().toArray(), range); + + double[] data = {5, 3, 1, 1, 5, Double.NaN, 3, 9, Double.POSITIVE_INFINITY, + Double.NEGATIVE_INFINITY, 2, 9, 1, 0, 8, Double.NaN, -0.0}; + double[] expected = {Double.NEGATIVE_INFINITY, -0.0, 0, 1, 2, 3, 5, 8, 9, + Double.POSITIVE_INFINITY, Double.NaN}; + assertEquals(DoubleStream.of(data).sorted().distinct().toArray(), expected); + assertEquals(DoubleStream.of(data).parallel().sorted().distinct().toArray(), expected); + } + } + public void testSortSort() { Random r = new Random(); diff -r 45cd7cc65382 -r 1258d14cf2cc jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java Sat Apr 30 00:30:31 2016 +0100 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java Fri Apr 29 16:57:57 2016 -0700 @@ -28,13 +28,21 @@ import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.Spliterator; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.IntConsumer; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +/** + * @test + * @bug 8153293 + */ @Test public class IntPrimitiveOpsTests { @@ -85,6 +93,29 @@ assertEquals(sum, 15); } + public void testFlags() { + assertTrue(IntStream.range(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(IntStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(IntStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + + assertTrue(IntStream.range(1, 10).asLongStream().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(IntStream.of(1, 10).asLongStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(IntStream.of(1, 10).asLongStream().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + + assertTrue(IntStream.range(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + } + public void testToArray() { { int[] array = IntStream.range(1, 10).map(i -> i * 2).toArray(); @@ -115,6 +146,35 @@ } } + public void testSortDistinct() { + { + int[] range = IntStream.range(0, 10).toArray(); + + assertEquals(IntStream.range(0, 10).sorted().distinct().toArray(), range); + assertEquals(IntStream.range(0, 10).parallel().sorted().distinct().toArray(), range); + + int[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8}; + int[] expected = {0, 1, 2, 3, 5, 8, 9}; + assertEquals(IntStream.of(data).sorted().distinct().toArray(), expected); + assertEquals(IntStream.of(data).parallel().sorted().distinct().toArray(), expected); + } + + { + int[] input = new Random().ints(100, -10, 10).map(x -> x+Integer.MAX_VALUE).toArray(); + TreeSet longs = new TreeSet<>(); + for(int i : input) longs.add((long)i); + long[] expectedLongs = longs.stream().mapToLong(Long::longValue).toArray(); + assertEquals(IntStream.of(input).sorted().asLongStream().sorted().distinct().toArray(), + expectedLongs); + + TreeSet doubles = new TreeSet<>(); + for(int i : input) doubles.add((double)i); + double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray(); + assertEquals(IntStream.of(input).sorted().distinct().asDoubleStream() + .sorted().distinct().toArray(), expectedDoubles); + } + } + public void testSortSort() { Random r = new Random(); diff -r 45cd7cc65382 -r 1258d14cf2cc jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java Sat Apr 30 00:30:31 2016 +0100 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java Fri Apr 29 16:57:57 2016 -0700 @@ -28,13 +28,21 @@ import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.Spliterator; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; import java.util.function.LongConsumer; import java.util.stream.Collectors; import java.util.stream.LongStream; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +/** + * @test + * @bug 8153293 + */ @Test public class LongPrimitiveOpsTests { @@ -85,6 +93,22 @@ assertEquals(sum, 15); } + public void testFlags() { + assertTrue(LongStream.range(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(LongStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(LongStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + + assertTrue(LongStream.range(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(LongStream.range(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + assertFalse(LongStream.of(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + } + public void testToArray() { { long[] array = LongStream.range(1, 10).map(i -> i * 2).toArray(); @@ -115,6 +139,30 @@ } } + public void testSortDistinct() { + { + long[] range = LongStream.range(0, 10).toArray(); + + assertEquals(LongStream.range(0, 10).sorted().distinct().toArray(), range); + assertEquals(LongStream.range(0, 10).parallel().sorted().distinct().toArray(), range); + + long[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8}; + long[] expected = {0, 1, 2, 3, 5, 8, 9}; + assertEquals(LongStream.of(data).sorted().distinct().toArray(), expected); + assertEquals(LongStream.of(data).parallel().sorted().distinct().toArray(), expected); + } + + { + long[] input = new Random().longs(100, -10, 10).map(x -> x+Long.MAX_VALUE).toArray(); + + TreeSet doubles = new TreeSet<>(); + for(long i : input) doubles.add((double)i); + double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray(); + assertEquals(LongStream.of(input).sorted().distinct().asDoubleStream() + .sorted().distinct().toArray(), expectedDoubles); + } + } + public void testSortSort() { Random r = new Random();