8153293: Preserve SORTED and DISTINCT characteristics for boxed() and asLongStream() operations
Reviewed-by: psandoz
This commit is contained in:
parent
bab1d3912a
commit
3ccd7f2289
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user