8178117: Add public state constructors for Int/Long/DoubleSummaryStatistics
Reviewed-by: psandoz, bpb, briangoetz
This commit is contained in:
parent
c6be2c363a
commit
58faa32cfe
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,6 +26,7 @@ package java.util;
|
|||||||
|
|
||||||
import java.util.function.DoubleConsumer;
|
import java.util.function.DoubleConsumer;
|
||||||
import java.util.stream.Collector;
|
import java.util.stream.Collector;
|
||||||
|
import java.util.stream.DoubleStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A state object for collecting statistics such as count, min, max, sum, and
|
* A state object for collecting statistics such as count, min, max, sum, and
|
||||||
@ -69,12 +70,65 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
|
|||||||
private double max = Double.NEGATIVE_INFINITY;
|
private double max = Double.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an empty instance with zero count, zero sum,
|
* Constructs an empty instance with zero count, zero sum,
|
||||||
* {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}
|
* {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}
|
||||||
* max and zero average.
|
* max and zero average.
|
||||||
*/
|
*/
|
||||||
public DoubleSummaryStatistics() { }
|
public DoubleSummaryStatistics() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a non-empty instance with the specified {@code count},
|
||||||
|
* {@code min}, {@code max}, and {@code sum}.
|
||||||
|
*
|
||||||
|
* <p>If {@code count} is zero then the remaining arguments are ignored and
|
||||||
|
* an empty instance is constructed.
|
||||||
|
*
|
||||||
|
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
|
||||||
|
* is thrown. The necessary consistent argument conditions are:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code count >= 0}</li>
|
||||||
|
* <li>{@code (min <= max && !isNaN(sum)) || (isNaN(min) && isNaN(max) && isNaN(sum))}</li>
|
||||||
|
* </ul>
|
||||||
|
* @apiNote
|
||||||
|
* The enforcement of argument correctness means that the retrieved set of
|
||||||
|
* recorded values obtained from a {@code DoubleSummaryStatistics} source
|
||||||
|
* instance may not be a legal set of arguments for this constructor due to
|
||||||
|
* arithmetic overflow of the source's recorded count of values.
|
||||||
|
* The consistent argument conditions are not sufficient to prevent the
|
||||||
|
* creation of an internally inconsistent instance. An example of such a
|
||||||
|
* state would be an instance with: {@code count} = 2, {@code min} = 1,
|
||||||
|
* {@code max} = 2, and {@code sum} = 0.
|
||||||
|
*
|
||||||
|
* @param count the count of values
|
||||||
|
* @param min the minimum value
|
||||||
|
* @param max the maximum value
|
||||||
|
* @param sum the sum of all values
|
||||||
|
* @throws IllegalArgumentException if the arguments are inconsistent
|
||||||
|
* @since 10
|
||||||
|
*/
|
||||||
|
public DoubleSummaryStatistics(long count, double min, double max, double sum)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
if (count < 0L) {
|
||||||
|
throw new IllegalArgumentException("Negative count value");
|
||||||
|
} else if (count > 0L) {
|
||||||
|
if (min > max)
|
||||||
|
throw new IllegalArgumentException("Minimum greater than maximum");
|
||||||
|
|
||||||
|
// All NaN or non NaN
|
||||||
|
var ncount = DoubleStream.of(min, max, sum).filter(Double::isNaN).count();
|
||||||
|
if (ncount > 0 && ncount < 3)
|
||||||
|
throw new IllegalArgumentException("Some, not all, of the minimum, maximum, or sum is NaN");
|
||||||
|
|
||||||
|
this.count = count;
|
||||||
|
this.sum = sum;
|
||||||
|
this.simpleSum = sum;
|
||||||
|
this.sumCompensation = 0.0d;
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
// Use default field values if count == 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records another value into the summary information.
|
* Records another value into the summary information.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -69,12 +69,57 @@ public class IntSummaryStatistics implements IntConsumer {
|
|||||||
private int max = Integer.MIN_VALUE;
|
private int max = Integer.MIN_VALUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an empty instance with zero count, zero sum,
|
* Constructs an empty instance with zero count, zero sum,
|
||||||
* {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
|
* {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
|
||||||
* average.
|
* average.
|
||||||
*/
|
*/
|
||||||
public IntSummaryStatistics() { }
|
public IntSummaryStatistics() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a non-empty instance with the specified {@code count},
|
||||||
|
* {@code min}, {@code max}, and {@code sum}.
|
||||||
|
*
|
||||||
|
* <p>If {@code count} is zero then the remaining arguments are ignored and
|
||||||
|
* an empty instance is constructed.
|
||||||
|
*
|
||||||
|
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
|
||||||
|
* is thrown. The necessary consistent argument conditions are:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code count >= 0}</li>
|
||||||
|
* <li>{@code min <= max}</li>
|
||||||
|
* </ul>
|
||||||
|
* @apiNote
|
||||||
|
* The enforcement of argument correctness means that the retrieved set of
|
||||||
|
* recorded values obtained from a {@code IntSummaryStatistics} source
|
||||||
|
* instance may not be a legal set of arguments for this constructor due to
|
||||||
|
* arithmetic overflow of the source's recorded count of values.
|
||||||
|
* The consistent argument conditions are not sufficient to prevent the
|
||||||
|
* creation of an internally inconsistent instance. An example of such a
|
||||||
|
* state would be an instance with: {@code count} = 2, {@code min} = 1,
|
||||||
|
* {@code max} = 2, and {@code sum} = 0.
|
||||||
|
*
|
||||||
|
* @param count the count of values
|
||||||
|
* @param min the minimum value
|
||||||
|
* @param max the maximum value
|
||||||
|
* @param sum the sum of all values
|
||||||
|
* @throws IllegalArgumentException if the arguments are inconsistent
|
||||||
|
* @since 10
|
||||||
|
*/
|
||||||
|
public IntSummaryStatistics(long count, int min, int max, long sum)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
if (count < 0L) {
|
||||||
|
throw new IllegalArgumentException("Negative count value");
|
||||||
|
} else if (count > 0L) {
|
||||||
|
if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
|
||||||
|
|
||||||
|
this.count = count;
|
||||||
|
this.sum = sum;
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
// Use default field values if count == 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records a new value into the summary information
|
* Records a new value into the summary information
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -70,12 +70,57 @@ public class LongSummaryStatistics implements LongConsumer, IntConsumer {
|
|||||||
private long max = Long.MIN_VALUE;
|
private long max = Long.MIN_VALUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an empty instance with zero count, zero sum,
|
* Constructs an empty instance with zero count, zero sum,
|
||||||
* {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
|
* {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
|
||||||
* average.
|
* average.
|
||||||
*/
|
*/
|
||||||
public LongSummaryStatistics() { }
|
public LongSummaryStatistics() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a non-empty instance with the specified {@code count},
|
||||||
|
* {@code min}, {@code max}, and {@code sum}.
|
||||||
|
*
|
||||||
|
* <p>If {@code count} is zero then the remaining arguments are ignored and
|
||||||
|
* an empty instance is constructed.
|
||||||
|
*
|
||||||
|
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
|
||||||
|
* is thrown. The necessary consistent argument conditions are:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code count >= 0}</li>
|
||||||
|
* <li>{@code min <= max}</li>
|
||||||
|
* </ul>
|
||||||
|
* @apiNote
|
||||||
|
* The enforcement of argument correctness means that the retrieved set of
|
||||||
|
* recorded values obtained from a {@code LongSummaryStatistics} source
|
||||||
|
* instance may not be a legal set of arguments for this constructor due to
|
||||||
|
* arithmetic overflow of the source's recorded count of values.
|
||||||
|
* The consistent argument conditions are not sufficient to prevent the
|
||||||
|
* creation of an internally inconsistent instance. An example of such a
|
||||||
|
* state would be an instance with: {@code count} = 2, {@code min} = 1,
|
||||||
|
* {@code max} = 2, and {@code sum} = 0.
|
||||||
|
*
|
||||||
|
* @param count the count of values
|
||||||
|
* @param min the minimum value
|
||||||
|
* @param max the maximum value
|
||||||
|
* @param sum the sum of all values
|
||||||
|
* @throws IllegalArgumentException if the arguments are inconsistent
|
||||||
|
* @since 10
|
||||||
|
*/
|
||||||
|
public LongSummaryStatistics(long count, long min, long max, long sum)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
if (count < 0L) {
|
||||||
|
throw new IllegalArgumentException("Negative count value");
|
||||||
|
} else if (count > 0L) {
|
||||||
|
if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
|
||||||
|
|
||||||
|
this.count = count;
|
||||||
|
this.sum = sum;
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
// Use default field values if count == 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records a new {@code int} value into the summary information.
|
* Records a new {@code int} value into the summary information.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -24,7 +24,7 @@
|
|||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @summary primtive stream collection with summary statistics
|
* @summary primtive stream collection with summary statistics
|
||||||
* @bug 8044047
|
* @bug 8044047 8178117
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.openjdk.tests.java.util.stream;
|
package org.openjdk.tests.java.util.stream;
|
||||||
@ -91,11 +91,19 @@ public class CollectAndSummaryStatisticsTest extends OpTestCase {
|
|||||||
instances.add(countTo(1000).stream().mapToInt(i -> i).collect(IntSummaryStatistics::new,
|
instances.add(countTo(1000).stream().mapToInt(i -> i).collect(IntSummaryStatistics::new,
|
||||||
IntSummaryStatistics::accept,
|
IntSummaryStatistics::accept,
|
||||||
IntSummaryStatistics::combine));
|
IntSummaryStatistics::combine));
|
||||||
|
instances.add(countTo(1000).stream().mapToInt(i -> i).collect(() -> new IntSummaryStatistics(0, -1, 1001, 2),
|
||||||
|
IntSummaryStatistics::accept,
|
||||||
|
IntSummaryStatistics::combine));
|
||||||
instances.add(countTo(1000).parallelStream().collect(Collectors.summarizingInt(i -> i)));
|
instances.add(countTo(1000).parallelStream().collect(Collectors.summarizingInt(i -> i)));
|
||||||
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).summaryStatistics());
|
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).summaryStatistics());
|
||||||
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).collect(IntSummaryStatistics::new,
|
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).collect(IntSummaryStatistics::new,
|
||||||
IntSummaryStatistics::accept,
|
IntSummaryStatistics::accept,
|
||||||
IntSummaryStatistics::combine));
|
IntSummaryStatistics::combine));
|
||||||
|
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).collect(() -> new IntSummaryStatistics(0, -1, 1001, 2),
|
||||||
|
IntSummaryStatistics::accept,
|
||||||
|
IntSummaryStatistics::combine));
|
||||||
|
IntSummaryStatistics original = instances.get(0);
|
||||||
|
instances.add(new IntSummaryStatistics(original.getCount(), original.getMin(), original.getMax(), original.getSum()));
|
||||||
|
|
||||||
for (IntSummaryStatistics stats : instances) {
|
for (IntSummaryStatistics stats : instances) {
|
||||||
assertEquals(stats.getCount(), 1000);
|
assertEquals(stats.getCount(), 1000);
|
||||||
@ -104,6 +112,9 @@ public class CollectAndSummaryStatisticsTest extends OpTestCase {
|
|||||||
assertEquals(stats.getMax(), 1000);
|
assertEquals(stats.getMax(), 1000);
|
||||||
assertEquals(stats.getMin(), 1);
|
assertEquals(stats.getMin(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new IntSummaryStatistics(-1, 0, 0, 0));
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new IntSummaryStatistics(1, 3, 2, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -114,11 +125,19 @@ public class CollectAndSummaryStatisticsTest extends OpTestCase {
|
|||||||
instances.add(countTo(1000).stream().mapToLong(i -> i).collect(LongSummaryStatistics::new,
|
instances.add(countTo(1000).stream().mapToLong(i -> i).collect(LongSummaryStatistics::new,
|
||||||
LongSummaryStatistics::accept,
|
LongSummaryStatistics::accept,
|
||||||
LongSummaryStatistics::combine));
|
LongSummaryStatistics::combine));
|
||||||
|
instances.add(countTo(1000).stream().mapToInt(i -> i).collect(() -> new LongSummaryStatistics(0, -1, 1001, 2),
|
||||||
|
LongSummaryStatistics::accept,
|
||||||
|
LongSummaryStatistics::combine));
|
||||||
instances.add(countTo(1000).parallelStream().collect(Collectors.summarizingLong(i -> i)));
|
instances.add(countTo(1000).parallelStream().collect(Collectors.summarizingLong(i -> i)));
|
||||||
instances.add(countTo(1000).parallelStream().mapToLong(i -> i).summaryStatistics());
|
instances.add(countTo(1000).parallelStream().mapToLong(i -> i).summaryStatistics());
|
||||||
instances.add(countTo(1000).parallelStream().mapToLong(i -> i).collect(LongSummaryStatistics::new,
|
instances.add(countTo(1000).parallelStream().mapToLong(i -> i).collect(LongSummaryStatistics::new,
|
||||||
LongSummaryStatistics::accept,
|
LongSummaryStatistics::accept,
|
||||||
LongSummaryStatistics::combine));
|
LongSummaryStatistics::combine));
|
||||||
|
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).collect(() -> new LongSummaryStatistics(0, -1, 1001, 2),
|
||||||
|
LongSummaryStatistics::accept,
|
||||||
|
LongSummaryStatistics::combine));
|
||||||
|
LongSummaryStatistics original = instances.get(0);
|
||||||
|
instances.add(new LongSummaryStatistics(original.getCount(), original.getMin(), original.getMax(), original.getSum()));
|
||||||
|
|
||||||
for (LongSummaryStatistics stats : instances) {
|
for (LongSummaryStatistics stats : instances) {
|
||||||
assertEquals(stats.getCount(), 1000);
|
assertEquals(stats.getCount(), 1000);
|
||||||
@ -127,6 +146,9 @@ public class CollectAndSummaryStatisticsTest extends OpTestCase {
|
|||||||
assertEquals(stats.getMax(), 1000L);
|
assertEquals(stats.getMax(), 1000L);
|
||||||
assertEquals(stats.getMin(), 1L);
|
assertEquals(stats.getMin(), 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new LongSummaryStatistics(-1, 0, 0, 0));
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new LongSummaryStatistics(1, 3, 2, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDoubleStatistics() {
|
public void testDoubleStatistics() {
|
||||||
@ -136,11 +158,19 @@ public class CollectAndSummaryStatisticsTest extends OpTestCase {
|
|||||||
instances.add(countTo(1000).stream().mapToDouble(i -> i).collect(DoubleSummaryStatistics::new,
|
instances.add(countTo(1000).stream().mapToDouble(i -> i).collect(DoubleSummaryStatistics::new,
|
||||||
DoubleSummaryStatistics::accept,
|
DoubleSummaryStatistics::accept,
|
||||||
DoubleSummaryStatistics::combine));
|
DoubleSummaryStatistics::combine));
|
||||||
|
instances.add(countTo(1000).stream().mapToInt(i -> i).collect(() -> new DoubleSummaryStatistics(0, -1, 1001, 2),
|
||||||
|
DoubleSummaryStatistics::accept,
|
||||||
|
DoubleSummaryStatistics::combine));
|
||||||
instances.add(countTo(1000).parallelStream().collect(Collectors.summarizingDouble(i -> i)));
|
instances.add(countTo(1000).parallelStream().collect(Collectors.summarizingDouble(i -> i)));
|
||||||
instances.add(countTo(1000).parallelStream().mapToDouble(i -> i).summaryStatistics());
|
instances.add(countTo(1000).parallelStream().mapToDouble(i -> i).summaryStatistics());
|
||||||
instances.add(countTo(1000).parallelStream().mapToDouble(i -> i).collect(DoubleSummaryStatistics::new,
|
instances.add(countTo(1000).parallelStream().mapToDouble(i -> i).collect(DoubleSummaryStatistics::new,
|
||||||
DoubleSummaryStatistics::accept,
|
DoubleSummaryStatistics::accept,
|
||||||
DoubleSummaryStatistics::combine));
|
DoubleSummaryStatistics::combine));
|
||||||
|
instances.add(countTo(1000).parallelStream().mapToInt(i -> i).collect(() -> new DoubleSummaryStatistics(0, -1, 1001, 2),
|
||||||
|
DoubleSummaryStatistics::accept,
|
||||||
|
DoubleSummaryStatistics::combine));
|
||||||
|
DoubleSummaryStatistics original = instances.get(0);
|
||||||
|
instances.add(new DoubleSummaryStatistics(original.getCount(), original.getMin(), original.getMax(), original.getSum()));
|
||||||
|
|
||||||
for (DoubleSummaryStatistics stats : instances) {
|
for (DoubleSummaryStatistics stats : instances) {
|
||||||
assertEquals(stats.getCount(), 1000);
|
assertEquals(stats.getCount(), 1000);
|
||||||
@ -149,5 +179,18 @@ public class CollectAndSummaryStatisticsTest extends OpTestCase {
|
|||||||
assertEquals(stats.getMax(), 1000.0);
|
assertEquals(stats.getMax(), 1000.0);
|
||||||
assertEquals(stats.getMin(), 1.0);
|
assertEquals(stats.getMin(), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new DoubleSummaryStatistics(-1, 0, 0, 0));
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new DoubleSummaryStatistics(1, 3, 2, 0));
|
||||||
|
double[] values = {1.0, Double.NaN};
|
||||||
|
for (var min : values) {
|
||||||
|
for (var max : values) {
|
||||||
|
for (var sum : values) {
|
||||||
|
if (Double.isNaN(min) && Double.isNaN(max) && Double.isNaN(sum)) continue;
|
||||||
|
if (!Double.isNaN(min) && !Double.isNaN(max) && !Double.isNaN(sum)) continue;
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> new DoubleSummaryStatistics(1, min, max, sum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user