8153293: Preserve SORTED and DISTINCT characteristics for boxed() and asLongStream() operations

Reviewed-by: psandoz
This commit is contained in:
Tagir F. Valeev 2016-04-29 16:57:57 -07:00
parent bab1d3912a
commit 3ccd7f2289
6 changed files with 189 additions and 48 deletions

View File

@ -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 @@ abstract class DoublePipeline<E_IN>
return Nodes.doubleBuilder(exactSizeIfKnown);
}
private <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper, int opFlags) {
return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE, opFlags) {
@Override
Sink<Double> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedDouble<U>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.apply(t));
}
};
}
};
}
// DoubleStream
@ -184,7 +197,7 @@ abstract class DoublePipeline<E_IN>
@Override
public final Stream<Double> boxed() {
return mapToObj(Double::valueOf);
return mapToObj(Double::valueOf, 0);
}
@Override
@ -207,18 +220,7 @@ abstract class DoublePipeline<E_IN>
@Override
public final <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
Objects.requireNonNull(mapper);
return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedDouble<U>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.apply(t));
}
};
}
};
return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
}
@Override

View File

@ -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 @@ abstract class IntPipeline<E_IN>
return Nodes.intBuilder(exactSizeIfKnown);
}
private <U> Stream<U> mapToObj(IntFunction<? extends U> mapper, int opFlags) {
return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE, opFlags) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedInt<U>(sink) {
@Override
public void accept(int t) {
downstream.accept(mapper.apply(t));
}
};
}
};
}
// IntStream
@ -187,8 +200,7 @@ abstract class IntPipeline<E_IN>
@Override
public final LongStream asLongStream() {
return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE, 0) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedInt<Long>(sink) {
@ -203,8 +215,7 @@ abstract class IntPipeline<E_IN>
@Override
public final DoubleStream asDoubleStream() {
return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE, 0) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedInt<Double>(sink) {
@ -219,7 +230,7 @@ abstract class IntPipeline<E_IN>
@Override
public final Stream<Integer> boxed() {
return mapToObj(Integer::valueOf);
return mapToObj(Integer::valueOf, 0);
}
@Override
@ -242,18 +253,7 @@ abstract class IntPipeline<E_IN>
@Override
public final <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
Objects.requireNonNull(mapper);
return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedInt<U>(sink) {
@Override
public void accept(int t) {
downstream.accept(mapper.apply(t));
}
};
}
};
return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
}
@Override

View File

@ -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 @@ abstract class LongPipeline<E_IN>
return Nodes.longBuilder(exactSizeIfKnown);
}
private <U> Stream<U> mapToObj(LongFunction<? extends U> mapper, int opFlags) {
return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE, opFlags) {
@Override
Sink<Long> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedLong<U>(sink) {
@Override
public void accept(long t) {
downstream.accept(mapper.apply(t));
}
};
}
};
}
// LongStream
@ -184,8 +197,7 @@ abstract class LongPipeline<E_IN>
@Override
public final DoubleStream asDoubleStream() {
return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedLong<Double>(sink) {
@ -200,7 +212,7 @@ abstract class LongPipeline<E_IN>
@Override
public final Stream<Long> boxed() {
return mapToObj(Long::valueOf);
return mapToObj(Long::valueOf, 0);
}
@Override
@ -223,18 +235,7 @@ abstract class LongPipeline<E_IN>
@Override
public final <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
Objects.requireNonNull(mapper);
return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedLong<U>(sink) {
@Override
public void accept(long t) {
downstream.accept(mapper.apply(t));
}
};
}
};
return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
}
@Override

View File

@ -27,11 +27,18 @@ import org.testng.annotations.Test;
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 @@ public class DoublePrimitiveOpsTests {
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 class DoublePrimitiveOpsTests {
}
}
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();

View File

@ -28,13 +28,21 @@ import org.testng.annotations.Test;
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 @@ public class IntPrimitiveOpsTests {
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 class IntPrimitiveOpsTests {
}
}
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<Long> 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<Double> 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();

View File

@ -28,13 +28,21 @@ import org.testng.annotations.Test;
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 @@ public class LongPrimitiveOpsTests {
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 class LongPrimitiveOpsTests {
}
}
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<Double> 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();