From 958186c07127f1cd9bb9ba82da99da75745766df Mon Sep 17 00:00:00 2001 From: chrisn Date: Mon, 8 Jun 2020 15:23:01 -0700 Subject: [PATCH] Add Comparators.min/max RELNOTES=`collect`: Added two-element min and max methods to Comparators. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=315365436 --- .../common/collect/ComparatorsTest.java | 56 +++++++++++++++ .../google/common/collect/Comparators.java | 69 +++++++++++++++++++ .../common/collect/ComparatorsTest_gwt.java | 20 ++++++ .../common/collect/ComparatorsTest.java | 56 +++++++++++++++ .../google/common/collect/Comparators.java | 69 +++++++++++++++++++ 5 files changed, 270 insertions(+) diff --git a/android/guava-tests/test/com/google/common/collect/ComparatorsTest.java b/android/guava-tests/test/com/google/common/collect/ComparatorsTest.java index d5f88014b5f8..b30cb7646d43 100644 --- a/android/guava-tests/test/com/google/common/collect/ComparatorsTest.java +++ b/android/guava-tests/test/com/google/common/collect/ComparatorsTest.java @@ -16,6 +16,7 @@ package com.google.common.collect; +import static com.google.common.truth.Truth.assertThat; import static java.util.Arrays.asList; import com.google.common.annotations.GwtCompatible; @@ -71,4 +72,59 @@ public void testIsInStrictOrder() { assertTrue(Comparators.isInStrictOrder(Collections.singleton(1), Ordering.natural())); assertTrue(Comparators.isInStrictOrder(Collections.emptyList(), Ordering.natural())); } + + public void testMinMaxNatural() { + assertThat(Comparators.min(1, 2)).isEqualTo(1); + assertThat(Comparators.min(2, 1)).isEqualTo(1); + assertThat(Comparators.max(1, 2)).isEqualTo(2); + assertThat(Comparators.max(2, 1)).isEqualTo(2); + } + + public void testMinMaxNatural_equalInstances() { + Foo a = new Foo(1); + Foo b = new Foo(1); + assertThat(Comparators.min(a, b)).isSameInstanceAs(a); + assertThat(Comparators.max(a, b)).isSameInstanceAs(a); + } + + public void testMinMaxComparator() { + Comparator natural = Ordering.natural(); + Comparator reverse = Collections.reverseOrder(natural); + assertThat(Comparators.min(1, 2, reverse)).isEqualTo(2); + assertThat(Comparators.min(2, 1, reverse)).isEqualTo(2); + assertThat(Comparators.max(1, 2, reverse)).isEqualTo(1); + assertThat(Comparators.max(2, 1, reverse)).isEqualTo(1); + } + + public void testMinMaxComparator_equalInstances() { + Comparator natural = Ordering.natural(); + Comparator reverse = Collections.reverseOrder(natural); + Foo a = new Foo(1); + Foo b = new Foo(1); + assertThat(Comparators.min(a, b, reverse)).isSameInstanceAs(a); + assertThat(Comparators.max(a, b, reverse)).isSameInstanceAs(a); + } + + private static class Foo implements Comparable { + final Integer value; + + Foo(int value) { + this.value = value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean equals(Object o) { + return (o instanceof Foo) && ((Foo) o).value.equals(value); + } + + @Override + public int compareTo(Foo other) { + return value.compareTo(other.value); + } + } } diff --git a/android/guava/src/com/google/common/collect/Comparators.java b/android/guava/src/com/google/common/collect/Comparators.java index 9facdf54119d..7115f884f168 100644 --- a/android/guava/src/com/google/common/collect/Comparators.java +++ b/android/guava/src/com/google/common/collect/Comparators.java @@ -22,6 +22,7 @@ import com.google.common.annotations.GwtCompatible; import java.util.Comparator; import java.util.Iterator; +import org.checkerframework.checker.nullness.compatqual.NullableDecl; /** * Provides static methods for working with {@link Comparator} instances. For many other helpful @@ -103,4 +104,72 @@ public static boolean isInStrictOrder( } return true; } + + /** + * Returns the minimum of the two values. If the values compare as 0, the first is returned. + * + *

To find the minimum of more than two values, use {@code Collections.min(Arrays.asList(a, b, + * c))} (static imports recommended). + * + * @param a first value to compare, returned if less than or equal to b. + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable. + * @since NEXT + */ + @Beta + public static > T min(T a, T b) { + return (a.compareTo(b) <= 0) ? a : b; + } + + /** + * Returns the minimum of the two values, according to the given comparator. If the values compare + * as equal, the first is returned. + * + *

To find the minimum of more than two values, use {@code Collections.min(Arrays.asList(a, b, + * c), comparator)} (static imports recommended). + * + * @param a first value to compare, returned if less than or equal to b + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable using the given + * comparator. + * @since NEXT + */ + @Beta + public static T min(@NullableDecl T a, @NullableDecl T b, Comparator comparator) { + return (comparator.compare(a, b) <= 0) ? a : b; + } + + /** + * Returns the maximum of the two values. If the values compare as 0, the first is returned. + * + *

To find the maximum of more than two values, use {@code Collections.max(Arrays.asList(a, b, + * c))} (static imports recommended). + * + * @param a first value to compare, returned if greater than or equal to b. + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable. + * @since NEXT + */ + @Beta + public static > T max(T a, T b) { + return (a.compareTo(b) >= 0) ? a : b; + } + + /** + * Returns the maximum of the two values, according to the given comparator. If the values compare + * as equal, the first is returned. + * + *

To find the maximum of more than two values, use {@code Collections.max(Arrays.asList(a, b, + * c), comparator)} (static imports recommended). + * + * @param a first value to compare, returned if greater than or equal to b. + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable using the given + * comparator. + * @since NEXT + */ + @Beta + public static T max(@NullableDecl T a, @NullableDecl T b, Comparator comparator) { + return (comparator.compare(a, b) >= 0) ? a : b; + } } diff --git a/guava-gwt/test/com/google/common/collect/ComparatorsTest_gwt.java b/guava-gwt/test/com/google/common/collect/ComparatorsTest_gwt.java index d2e0e12c7569..de38d6a49322 100644 --- a/guava-gwt/test/com/google/common/collect/ComparatorsTest_gwt.java +++ b/guava-gwt/test/com/google/common/collect/ComparatorsTest_gwt.java @@ -52,4 +52,24 @@ public void testLexicographical() throws Exception { com.google.common.collect.ComparatorsTest testCase = new com.google.common.collect.ComparatorsTest(); testCase.testLexicographical(); } + +public void testMinMaxComparator() throws Exception { + com.google.common.collect.ComparatorsTest testCase = new com.google.common.collect.ComparatorsTest(); + testCase.testMinMaxComparator(); +} + +public void testMinMaxComparator_equalInstances() throws Exception { + com.google.common.collect.ComparatorsTest testCase = new com.google.common.collect.ComparatorsTest(); + testCase.testMinMaxComparator_equalInstances(); +} + +public void testMinMaxNatural() throws Exception { + com.google.common.collect.ComparatorsTest testCase = new com.google.common.collect.ComparatorsTest(); + testCase.testMinMaxNatural(); +} + +public void testMinMaxNatural_equalInstances() throws Exception { + com.google.common.collect.ComparatorsTest testCase = new com.google.common.collect.ComparatorsTest(); + testCase.testMinMaxNatural_equalInstances(); +} } diff --git a/guava-tests/test/com/google/common/collect/ComparatorsTest.java b/guava-tests/test/com/google/common/collect/ComparatorsTest.java index fb79e9e9d189..3f568c11555d 100644 --- a/guava-tests/test/com/google/common/collect/ComparatorsTest.java +++ b/guava-tests/test/com/google/common/collect/ComparatorsTest.java @@ -16,6 +16,7 @@ package com.google.common.collect; +import static com.google.common.truth.Truth.assertThat; import static java.util.Arrays.asList; import static java.util.Comparator.comparing; import static java.util.Comparator.naturalOrder; @@ -114,4 +115,59 @@ public void testEmptiesLast() { // Just demonstrate that no explicit type parameter is required comparator = Comparators.emptiesLast(naturalOrder()); } + + public void testMinMaxNatural() { + assertThat(Comparators.min(1, 2)).isEqualTo(1); + assertThat(Comparators.min(2, 1)).isEqualTo(1); + assertThat(Comparators.max(1, 2)).isEqualTo(2); + assertThat(Comparators.max(2, 1)).isEqualTo(2); + } + + public void testMinMaxNatural_equalInstances() { + Foo a = new Foo(1); + Foo b = new Foo(1); + assertThat(Comparators.min(a, b)).isSameInstanceAs(a); + assertThat(Comparators.max(a, b)).isSameInstanceAs(a); + } + + public void testMinMaxComparator() { + Comparator natural = Ordering.natural(); + Comparator reverse = Collections.reverseOrder(natural); + assertThat(Comparators.min(1, 2, reverse)).isEqualTo(2); + assertThat(Comparators.min(2, 1, reverse)).isEqualTo(2); + assertThat(Comparators.max(1, 2, reverse)).isEqualTo(1); + assertThat(Comparators.max(2, 1, reverse)).isEqualTo(1); + } + + public void testMinMaxComparator_equalInstances() { + Comparator natural = Ordering.natural(); + Comparator reverse = Collections.reverseOrder(natural); + Foo a = new Foo(1); + Foo b = new Foo(1); + assertThat(Comparators.min(a, b, reverse)).isSameInstanceAs(a); + assertThat(Comparators.max(a, b, reverse)).isSameInstanceAs(a); + } + + private static class Foo implements Comparable { + final Integer value; + + Foo(int value) { + this.value = value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean equals(Object o) { + return (o instanceof Foo) && ((Foo) o).value.equals(value); + } + + @Override + public int compareTo(Foo other) { + return value.compareTo(other.value); + } + } } diff --git a/guava/src/com/google/common/collect/Comparators.java b/guava/src/com/google/common/collect/Comparators.java index 06b398f3ce1e..b24ba7a85c41 100644 --- a/guava/src/com/google/common/collect/Comparators.java +++ b/guava/src/com/google/common/collect/Comparators.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collector; +import org.checkerframework.checker.nullness.qual.Nullable; /** * Provides static methods for working with {@link Comparator} instances. For many other helpful @@ -190,4 +191,72 @@ public static Comparator> emptiesLast(Comparator valu checkNotNull(valueComparator); return Comparator.comparing(o -> o.orElse(null), Comparator.nullsLast(valueComparator)); } + + /** + * Returns the minimum of the two values. If the values compare as 0, the first is returned. + * + *

To find the minimum of more than two values, use {@code Collections.min(Arrays.asList(a, b, + * c))} (static imports recommended). + * + * @param a first value to compare, returned if less than or equal to b. + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable. + * @since NEXT + */ + @Beta + public static > T min(T a, T b) { + return (a.compareTo(b) <= 0) ? a : b; + } + + /** + * Returns the minimum of the two values, according to the given comparator. If the values compare + * as equal, the first is returned. + * + *

To find the minimum of more than two values, use {@code Collections.min(Arrays.asList(a, b, + * c), comparator)} (static imports recommended). + * + * @param a first value to compare, returned if less than or equal to b + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable using the given + * comparator. + * @since NEXT + */ + @Beta + public static T min(@Nullable T a, @Nullable T b, Comparator comparator) { + return (comparator.compare(a, b) <= 0) ? a : b; + } + + /** + * Returns the maximum of the two values. If the values compare as 0, the first is returned. + * + *

To find the maximum of more than two values, use {@code Collections.max(Arrays.asList(a, b, + * c))} (static imports recommended). + * + * @param a first value to compare, returned if greater than or equal to b. + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable. + * @since NEXT + */ + @Beta + public static > T max(T a, T b) { + return (a.compareTo(b) >= 0) ? a : b; + } + + /** + * Returns the maximum of the two values, according to the given comparator. If the values compare + * as equal, the first is returned. + * + *

To find the maximum of more than two values, use {@code Collections.max(Arrays.asList(a, b, + * c), comparator)} (static imports recommended). + * + * @param a first value to compare, returned if greater than or equal to b. + * @param b second value to compare. + * @throws ClassCastException if the parameters are not mutually comparable using the given + * comparator. + * @since NEXT + */ + @Beta + public static T max(@Nullable T a, @Nullable T b, Comparator comparator) { + return (comparator.compare(a, b) >= 0) ? a : b; + } }