Skip to content

Commit f9f3fff

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Expose more Java 8 APIs to Android users.
RELNOTES=Exposed some additional Java 8 APIs to Android users. PiperOrigin-RevId: 688998996
1 parent 10c64d9 commit f9f3fff

File tree

19 files changed

+574
-16
lines changed

19 files changed

+574
-16
lines changed

android/guava-tests/test/com/google/common/collect/ComparatorsTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
import static com.google.common.collect.Comparators.min;
2121
import static com.google.common.truth.Truth.assertThat;
2222
import static java.util.Arrays.asList;
23+
import static java.util.Comparator.comparing;
24+
import static java.util.Comparator.naturalOrder;
2325

2426
import com.google.common.annotations.GwtCompatible;
2527
import com.google.common.collect.testing.Helpers;
2628
import com.google.common.testing.EqualsTester;
2729
import java.util.Collections;
2830
import java.util.Comparator;
31+
import java.util.Optional;
2932
import junit.framework.TestCase;
3033
import org.checkerframework.checker.nullness.qual.Nullable;
3134

@@ -76,6 +79,30 @@ public void testIsInStrictOrder() {
7679
assertTrue(Comparators.isInStrictOrder(Collections.<Integer>emptyList(), Ordering.natural()));
7780
}
7881

82+
public void testEmptiesFirst() {
83+
Optional<String> empty = Optional.empty();
84+
Optional<String> abc = Optional.of("abc");
85+
Optional<String> z = Optional.of("z");
86+
87+
Comparator<Optional<String>> comparator = Comparators.emptiesFirst(comparing(String::length));
88+
Helpers.testComparator(comparator, empty, z, abc);
89+
90+
// Just demonstrate that no explicit type parameter is required
91+
Comparator<Optional<String>> unused = Comparators.emptiesFirst(naturalOrder());
92+
}
93+
94+
public void testEmptiesLast() {
95+
Optional<String> empty = Optional.empty();
96+
Optional<String> abc = Optional.of("abc");
97+
Optional<String> z = Optional.of("z");
98+
99+
Comparator<Optional<String>> comparator = Comparators.emptiesLast(comparing(String::length));
100+
Helpers.testComparator(comparator, z, abc, empty);
101+
102+
// Just demonstrate that no explicit type parameter is required
103+
Comparator<Optional<String>> unused = Comparators.emptiesLast(naturalOrder());
104+
}
105+
79106
public void testMinMaxNatural() {
80107
assertThat(min(1, 2)).isEqualTo(1);
81108
assertThat(min(2, 1)).isEqualTo(1);

android/guava-tests/test/com/google/common/math/StatsAccumulatorTest.java

+56
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,25 @@
3636
import static com.google.common.math.StatsTesting.MANY_VALUES_MEAN;
3737
import static com.google.common.math.StatsTesting.MANY_VALUES_MIN;
3838
import static com.google.common.math.StatsTesting.MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS;
39+
import static com.google.common.math.StatsTesting.MEGA_STREAM_COUNT;
40+
import static com.google.common.math.StatsTesting.MEGA_STREAM_MAX;
41+
import static com.google.common.math.StatsTesting.MEGA_STREAM_MEAN;
42+
import static com.google.common.math.StatsTesting.MEGA_STREAM_MIN;
43+
import static com.google.common.math.StatsTesting.MEGA_STREAM_POPULATION_VARIANCE;
3944
import static com.google.common.math.StatsTesting.ONE_VALUE;
4045
import static com.google.common.math.StatsTesting.OTHER_ONE_VALUE;
4146
import static com.google.common.math.StatsTesting.TWO_VALUES;
4247
import static com.google.common.math.StatsTesting.TWO_VALUES_MAX;
4348
import static com.google.common.math.StatsTesting.TWO_VALUES_MEAN;
4449
import static com.google.common.math.StatsTesting.TWO_VALUES_MIN;
4550
import static com.google.common.math.StatsTesting.TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS;
51+
import static com.google.common.math.StatsTesting.megaPrimitiveDoubleStream;
52+
import static com.google.common.math.StatsTesting.megaPrimitiveDoubleStreamPart1;
53+
import static com.google.common.math.StatsTesting.megaPrimitiveDoubleStreamPart2;
4654
import static com.google.common.truth.Truth.assertThat;
4755
import static com.google.common.truth.Truth.assertWithMessage;
4856
import static java.lang.Math.sqrt;
57+
import static java.util.stream.DoubleStream.concat;
4958
import static org.junit.Assert.assertThrows;
5059

5160
import com.google.common.collect.ImmutableList;
@@ -622,4 +631,51 @@ public void testMin() {
622631
assertThat(longManyValuesAccumulatorByAddAllIterator.min()).isEqualTo(LONG_MANY_VALUES_MIN);
623632
assertThat(longManyValuesAccumulatorByAddAllVarargs.min()).isEqualTo(LONG_MANY_VALUES_MIN);
624633
}
634+
635+
public void testVerifyMegaStreamHalves() {
636+
assertThat(
637+
concat(megaPrimitiveDoubleStreamPart1(), megaPrimitiveDoubleStreamPart2())
638+
.sorted()
639+
.toArray())
640+
.isEqualTo(megaPrimitiveDoubleStream().toArray());
641+
}
642+
643+
public void testAddAllPrimitiveDoubleStream() {
644+
StatsAccumulator accumulator = new StatsAccumulator();
645+
accumulator.addAll(megaPrimitiveDoubleStreamPart1());
646+
accumulator.addAll(megaPrimitiveDoubleStreamPart2());
647+
assertThat(accumulator.count()).isEqualTo(MEGA_STREAM_COUNT);
648+
assertThat(accumulator.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
649+
assertThat(accumulator.populationVariance())
650+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
651+
.of(MEGA_STREAM_POPULATION_VARIANCE);
652+
assertThat(accumulator.min()).isEqualTo(MEGA_STREAM_MIN);
653+
assertThat(accumulator.max()).isEqualTo(MEGA_STREAM_MAX);
654+
}
655+
656+
public void testAddAllPrimitiveIntStream() {
657+
StatsAccumulator accumulator = new StatsAccumulator();
658+
accumulator.addAll(megaPrimitiveDoubleStreamPart1().mapToInt(x -> (int) x));
659+
accumulator.addAll(megaPrimitiveDoubleStreamPart2().mapToInt(x -> (int) x));
660+
assertThat(accumulator.count()).isEqualTo(MEGA_STREAM_COUNT);
661+
assertThat(accumulator.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
662+
assertThat(accumulator.populationVariance())
663+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
664+
.of(MEGA_STREAM_POPULATION_VARIANCE);
665+
assertThat(accumulator.min()).isEqualTo(MEGA_STREAM_MIN);
666+
assertThat(accumulator.max()).isEqualTo(MEGA_STREAM_MAX);
667+
}
668+
669+
public void testAddAllPrimitiveLongStream() {
670+
StatsAccumulator accumulator = new StatsAccumulator();
671+
accumulator.addAll(megaPrimitiveDoubleStreamPart1().mapToLong(x -> (long) x));
672+
accumulator.addAll(megaPrimitiveDoubleStreamPart2().mapToLong(x -> (long) x));
673+
assertThat(accumulator.count()).isEqualTo(MEGA_STREAM_COUNT);
674+
assertThat(accumulator.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
675+
assertThat(accumulator.populationVariance())
676+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
677+
.of(MEGA_STREAM_POPULATION_VARIANCE);
678+
assertThat(accumulator.min()).isEqualTo(MEGA_STREAM_MIN);
679+
assertThat(accumulator.max()).isEqualTo(MEGA_STREAM_MAX);
680+
}
625681
}

android/guava-tests/test/com/google/common/math/StatsTest.java

+101
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.common.math;
1818

19+
import static com.google.common.math.Stats.toStats;
1920
import static com.google.common.math.StatsTesting.ALLOWED_ERROR;
2021
import static com.google.common.math.StatsTesting.ALL_MANY_VALUES;
2122
import static com.google.common.math.StatsTesting.ALL_STATS;
@@ -55,6 +56,11 @@
5556
import static com.google.common.math.StatsTesting.MANY_VALUES_STATS_SNAPSHOT;
5657
import static com.google.common.math.StatsTesting.MANY_VALUES_STATS_VARARGS;
5758
import static com.google.common.math.StatsTesting.MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS;
59+
import static com.google.common.math.StatsTesting.MEGA_STREAM_COUNT;
60+
import static com.google.common.math.StatsTesting.MEGA_STREAM_MAX;
61+
import static com.google.common.math.StatsTesting.MEGA_STREAM_MEAN;
62+
import static com.google.common.math.StatsTesting.MEGA_STREAM_MIN;
63+
import static com.google.common.math.StatsTesting.MEGA_STREAM_POPULATION_VARIANCE;
5864
import static com.google.common.math.StatsTesting.ONE_VALUE;
5965
import static com.google.common.math.StatsTesting.ONE_VALUE_STATS;
6066
import static com.google.common.math.StatsTesting.TWO_VALUES;
@@ -63,12 +69,14 @@
6369
import static com.google.common.math.StatsTesting.TWO_VALUES_MIN;
6470
import static com.google.common.math.StatsTesting.TWO_VALUES_STATS;
6571
import static com.google.common.math.StatsTesting.TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS;
72+
import static com.google.common.math.StatsTesting.megaPrimitiveDoubleStream;
6673
import static com.google.common.truth.Truth.assertThat;
6774
import static com.google.common.truth.Truth.assertWithMessage;
6875
import static java.lang.Double.NEGATIVE_INFINITY;
6976
import static java.lang.Double.NaN;
7077
import static java.lang.Double.POSITIVE_INFINITY;
7178
import static java.lang.Math.sqrt;
79+
import static java.util.Arrays.stream;
7280
import static org.junit.Assert.assertThrows;
7381

7482
import com.google.common.collect.ImmutableList;
@@ -77,8 +85,10 @@
7785
import com.google.common.primitives.Longs;
7886
import com.google.common.testing.EqualsTester;
7987
import com.google.common.testing.SerializableTester;
88+
import java.math.BigDecimal;
8089
import java.nio.ByteBuffer;
8190
import java.nio.ByteOrder;
91+
import java.util.DoubleSummaryStatistics;
8292
import junit.framework.TestCase;
8393

8494
/**
@@ -401,6 +411,39 @@ public void testMin() {
401411
assertThat(LONG_MANY_VALUES_STATS_SNAPSHOT.min()).isEqualTo(LONG_MANY_VALUES_MIN);
402412
}
403413

414+
public void testOfPrimitiveDoubleStream() {
415+
Stats stats = Stats.of(megaPrimitiveDoubleStream());
416+
assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT);
417+
assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
418+
assertThat(stats.populationVariance())
419+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
420+
.of(MEGA_STREAM_POPULATION_VARIANCE);
421+
assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN);
422+
assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX);
423+
}
424+
425+
public void testOfPrimitiveIntStream() {
426+
Stats stats = Stats.of(megaPrimitiveDoubleStream().mapToInt(x -> (int) x));
427+
assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT);
428+
assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
429+
assertThat(stats.populationVariance())
430+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
431+
.of(MEGA_STREAM_POPULATION_VARIANCE);
432+
assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN);
433+
assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX);
434+
}
435+
436+
public void testOfPrimitiveLongStream() {
437+
Stats stats = Stats.of(megaPrimitiveDoubleStream().mapToLong(x -> (long) x));
438+
assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT);
439+
assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
440+
assertThat(stats.populationVariance())
441+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
442+
.of(MEGA_STREAM_POPULATION_VARIANCE);
443+
assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN);
444+
assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX);
445+
}
446+
404447
public void testEqualsAndHashCode() {
405448
new EqualsTester()
406449
.addEqualityGroup(
@@ -523,4 +566,62 @@ public void testFromByteArrayWithTooShortArrayInputThrowsIllegalArgumentExceptio
523566
.array();
524567
assertThrows(IllegalArgumentException.class, () -> Stats.fromByteArray(tooShortByteArray));
525568
}
569+
570+
public void testEquivalentStreams() {
571+
// For datasets of many double values created from an array, we test many combinations of finite
572+
// and non-finite values:
573+
for (ManyValues values : ALL_MANY_VALUES) {
574+
double[] array = values.asArray();
575+
Stats stats = Stats.of(array);
576+
// instance methods on Stats vs on instance methods on DoubleStream
577+
assertThat(stats.count()).isEqualTo(stream(array).count());
578+
assertEquivalent(stats.mean(), stream(array).average().getAsDouble());
579+
assertEquivalent(stats.sum(), stream(array).sum());
580+
assertEquivalent(stats.max(), stream(array).max().getAsDouble());
581+
assertEquivalent(stats.min(), stream(array).min().getAsDouble());
582+
// static method on Stats vs on instance method on DoubleStream
583+
assertEquivalent(Stats.meanOf(array), stream(array).average().getAsDouble());
584+
// instance methods on Stats vs instance methods on DoubleSummaryStatistics
585+
DoubleSummaryStatistics streamStats = stream(array).summaryStatistics();
586+
assertThat(stats.count()).isEqualTo(streamStats.getCount());
587+
assertEquivalent(stats.mean(), streamStats.getAverage());
588+
assertEquivalent(stats.sum(), streamStats.getSum());
589+
assertEquivalent(stats.max(), streamStats.getMax());
590+
assertEquivalent(stats.min(), streamStats.getMin());
591+
}
592+
}
593+
594+
private static void assertEquivalent(double actual, double expected) {
595+
if (expected == POSITIVE_INFINITY) {
596+
assertThat(actual).isPositiveInfinity();
597+
} else if (expected == NEGATIVE_INFINITY) {
598+
assertThat(actual).isNegativeInfinity();
599+
} else if (Double.isNaN(expected)) {
600+
assertThat(actual).isNaN();
601+
} else {
602+
assertThat(actual).isWithin(ALLOWED_ERROR).of(expected);
603+
}
604+
}
605+
606+
public void testBoxedDoubleStreamToStats() {
607+
Stats stats = megaPrimitiveDoubleStream().boxed().collect(toStats());
608+
assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT);
609+
assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
610+
assertThat(stats.populationVariance())
611+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
612+
.of(MEGA_STREAM_POPULATION_VARIANCE);
613+
assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN);
614+
assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX);
615+
}
616+
617+
public void testBoxedBigDecimalStreamToStats() {
618+
Stats stats = megaPrimitiveDoubleStream().mapToObj(BigDecimal::valueOf).collect(toStats());
619+
assertThat(stats.count()).isEqualTo(MEGA_STREAM_COUNT);
620+
assertThat(stats.mean()).isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT).of(MEGA_STREAM_MEAN);
621+
assertThat(stats.populationVariance())
622+
.isWithin(ALLOWED_ERROR * MEGA_STREAM_COUNT)
623+
.of(MEGA_STREAM_POPULATION_VARIANCE);
624+
assertThat(stats.min()).isEqualTo(MEGA_STREAM_MIN);
625+
assertThat(stats.max()).isEqualTo(MEGA_STREAM_MAX);
626+
}
526627
}

android/guava-tests/test/com/google/common/math/StatsTesting.java

+32
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.common.primitives.Ints;
3333
import java.math.BigInteger;
3434
import java.util.List;
35+
import java.util.stream.DoubleStream;
3536

3637
/**
3738
* Inputs, expected outputs, and helper methods for tests of {@link StatsAccumulator}, {@link
@@ -212,6 +213,37 @@ private static ImmutableList<ManyValues> createAll() {
212213
.divide(BigInteger.valueOf(16L))
213214
.doubleValue();
214215

216+
/**
217+
* Returns a stream of a million primitive doubles. The stream is parallel, which should cause
218+
* {@code collect} calls to run in multithreaded mode, so testing the combiner as well as the
219+
* supplier and accumulator.
220+
*/
221+
static DoubleStream megaPrimitiveDoubleStream() {
222+
return DoubleStream.iterate(0.0, x -> x + 1.0).limit(MEGA_STREAM_COUNT).parallel();
223+
}
224+
225+
/** Returns a stream containing half the values from {@link #megaPrimitiveDoubleStream}. */
226+
static DoubleStream megaPrimitiveDoubleStreamPart1() {
227+
return DoubleStream.iterate(0.0, x -> x + 2.0).limit(MEGA_STREAM_COUNT / 2).parallel();
228+
}
229+
230+
/**
231+
* Returns a stream containing the values from {@link #megaPrimitiveDoubleStream} not in {@link
232+
* #megaPrimitiveDoubleStreamPart1()}.
233+
*/
234+
static DoubleStream megaPrimitiveDoubleStreamPart2() {
235+
return DoubleStream.iterate(MEGA_STREAM_COUNT - 1.0, x -> x - 2.0)
236+
.limit(MEGA_STREAM_COUNT / 2)
237+
.parallel();
238+
}
239+
240+
static final long MEGA_STREAM_COUNT = isAndroid() ? 100 : 1_000_000;
241+
static final double MEGA_STREAM_MIN = 0.0;
242+
static final double MEGA_STREAM_MAX = MEGA_STREAM_COUNT - 1;
243+
static final double MEGA_STREAM_MEAN = MEGA_STREAM_MAX / 2;
244+
static final double MEGA_STREAM_POPULATION_VARIANCE =
245+
(MEGA_STREAM_COUNT - 1) * (MEGA_STREAM_COUNT + 1) / 12.0;
246+
215247
// Stats instances:
216248

217249
static final Stats EMPTY_STATS_VARARGS = Stats.of();

android/guava/src/com/google/common/collect/Comparators.java

+44
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
import java.util.Comparator;
2424
import java.util.Iterator;
2525
import java.util.List;
26+
import java.util.Optional;
2627
import java.util.stream.Collector;
28+
import javax.annotation.CheckForNull;
2729
import org.checkerframework.checker.nullness.qual.Nullable;
2830

2931
/**
@@ -170,6 +172,48 @@ private Comparators() {}
170172
return least(k, comparator.reversed());
171173
}
172174

175+
/**
176+
* Returns a comparator of {@link Optional} values which treats {@link Optional#empty} as less
177+
* than all other values, and orders the rest using {@code valueComparator} on the contained
178+
* value.
179+
*
180+
* @since NEXT (but since 22.0 in the JRE flavor)
181+
*/
182+
@SuppressWarnings("Java7ApiChecker")
183+
@IgnoreJRERequirement // Users will use this only if they're already using Optional.
184+
public static <T> Comparator<Optional<T>> emptiesFirst(Comparator<? super T> valueComparator) {
185+
checkNotNull(valueComparator);
186+
return Comparator.<Optional<T>, @Nullable T>comparing(
187+
o -> orElseNull(o), Comparator.nullsFirst(valueComparator));
188+
}
189+
190+
/**
191+
* Returns a comparator of {@link Optional} values which treats {@link Optional#empty} as greater
192+
* than all other values, and orders the rest using {@code valueComparator} on the contained
193+
* value.
194+
*
195+
* @since NEXT (but since 22.0 in the JRE flavor)
196+
*/
197+
@SuppressWarnings("Java7ApiChecker")
198+
@IgnoreJRERequirement // Users will use this only if they're already using Optional.
199+
public static <T> Comparator<Optional<T>> emptiesLast(Comparator<? super T> valueComparator) {
200+
checkNotNull(valueComparator);
201+
return Comparator.<Optional<T>, @Nullable T>comparing(
202+
o -> orElseNull(o), Comparator.nullsLast(valueComparator));
203+
}
204+
205+
@SuppressWarnings("Java7ApiChecker")
206+
@IgnoreJRERequirement // helper for emptiesFirst+emptiesLast
207+
/*
208+
* If we make these calls inline inside the lambda inside emptiesFirst()/emptiesLast(), we get an
209+
* Animal Sniffer error, despite the @IgnoreJRERequirement annotation there. For details, see
210+
* ImmutableSortedMultiset.
211+
*/
212+
@CheckForNull
213+
private static <T> T orElseNull(Optional<T> optional) {
214+
return optional.orElse(null);
215+
}
216+
173217
/**
174218
* Returns the minimum of the two values. If the values compare as 0, the first is returned.
175219
*

0 commit comments

Comments
 (0)