From c16c0e61c98780d4e5f13c007d0646837112f999 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 17 Nov 2015 14:11:42 +0100 Subject: [PATCH] 8141409: Arrays.equals accepting a Comparator Reviewed-by: rriggs --- .../share/classes/java/util/Arrays.java | 117 ++++++++++++++++-- .../java/util/Arrays/ArraysEqCmpTest.java | 35 +++++- 2 files changed, 139 insertions(+), 13 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/Arrays.java b/jdk/src/java.base/share/classes/java/util/Arrays.java index f172e508ca8..af64264b3f3 100644 --- a/jdk/src/java.base/share/classes/java/util/Arrays.java +++ b/jdk/src/java.base/share/classes/java/util/Arrays.java @@ -3305,6 +3305,103 @@ public class Arrays { return true; } + /** + * Returns {@code true} if the two specified arrays of Objects are + * equal to one another. + * + *

Two arrays are considered equal if both arrays contain the same number + * of elements, and all corresponding pairs of elements in the two arrays + * are equal. In other words, the two arrays are equal if they contain the + * same elements in the same order. Also, two array references are + * considered equal if both are {@code null}. + * + *

Two objects {@code e1} and {@code e2} are considered equal if, + * given the specified comparator, {@code cmp.compare(e1, e2) == 0}. + * + * @param a one array to be tested for equality + * @param a2 the other array to be tested for equality + * @param cmp the comparator to compare array elements + * @param the type of array elements + * @return {@code true} if the two arrays are equal + * @throws NullPointerException if the comparator is {@code null} + * @since 9 + */ + public static boolean equals(T[] a, T[] a2, Comparator cmp) { + Objects.requireNonNull(cmp); + if (a==a2) + return true; + if (a==null || a2==null) + return false; + + int length = a.length; + if (a2.length != length) + return false; + + for (int i=0; iequal to one another. + * + *

Two arrays are considered equal if the number of elements covered by + * each range is the same, and all corresponding pairs of elements over the + * specified ranges in the two arrays are equal. In other words, two arrays + * are equal if they contain, over the specified ranges, the same elements + * in the same order. + * + *

Two objects {@code e1} and {@code e2} are considered equal if, + * given the specified comparator, {@code cmp.compare(e1, e2) == 0}. + * + * @param a the first array to be tested for equality + * @param aFromIndex the index (inclusive) of the first element in the + * first array to be tested + * @param aToIndex the index (exclusive) of the last element in the + * first array to be tested + * @param b the second array to be tested fro equality + * @param bFromIndex the index (inclusive) of the first element in the + * second array to be tested + * @param bToIndex the index (exclusive) of the last element in the + * second array to be tested + * @param cmp the comparator to compare array elements + * @param the type of array elements + * @return {@code true} if the two arrays, over the specified ranges, are + * equal + * @throws IllegalArgumentException + * if {@code aFromIndex > aToIndex} or + * if {@code bFromIndex > bToIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code aFromIndex < 0 or aToIndex > a.length} or + * if {@code bFromIndex < 0 or bToIndex > b.length} + * @throws NullPointerException + * if either array or the comparator is {@code null} + * @since 9 + */ + public static boolean equals(T[] a, int aFromIndex, int aToIndex, + T[] b, int bFromIndex, int bToIndex, + Comparator cmp) { + Objects.requireNonNull(cmp); + rangeCheck(a.length, aFromIndex, aToIndex); + rangeCheck(b.length, bFromIndex, bToIndex); + + int aLength = aToIndex - aFromIndex; + int bLength = bToIndex - bFromIndex; + if (aLength != bLength) + return false; + + for (int i = 0; i < aLength; i++) { + if (cmp.compare(a[aFromIndex++], b[bFromIndex++]) != 0) + return false; + } + + return true; + } + // Filling /** @@ -8744,9 +8841,7 @@ public class Arrays { *

{@code
      *     pl >= 0 &&
      *     pl < Math.min(a.length, b.length) &&
-     *     IntStream.range(0, pl).
-     *         map(i -> cmp.compare(a[i], b[i])).
-     *         allMatch(c -> c == 0) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl, cmp)
      *     cmp.compare(a[pl], b[pl]) != 0
      * }
* Note that a common prefix length of {@code 0} indicates that the first @@ -8756,9 +8851,9 @@ public class Arrays { * prefix if the following expression is true: *
{@code
      *     a.length != b.length &&
-     *     IntStream.range(0, Math.min(a.length, b.length)).
-     *         map(i -> cmp.compare(a[i], b[i])).
-     *         allMatch(c -> c == 0) &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length),
+     *                   cmp)
      * }
* * @param a the first array to be tested for a mismatch @@ -8815,9 +8910,7 @@ public class Arrays { *
{@code
      *     pl >= 0 &&
      *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
-     *     IntStream.range(0, pl).
-     *         map(i -> cmp.compare(a[aFromIndex + i], b[bFromIndex + i])).
-     *         allMatch(c -> c == 0) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl, cmp) &&
      *     cmp.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
      * }
* Note that a common prefix length of {@code 0} indicates that the first @@ -8829,9 +8922,9 @@ public class Arrays { * if the following expression is true: *
{@code
      *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
-     *     IntStream.range(0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex)).
-     *         map(i -> cmp.compare(a[aFromIndex + i], b[bFromIndex + i])).
-     *         allMatch(c -> c == 0)
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   cmp)
      * }
* * @param a the first array to be tested for a mismatch diff --git a/jdk/test/java/util/Arrays/ArraysEqCmpTest.java b/jdk/test/java/util/Arrays/ArraysEqCmpTest.java index 590b71668b4..a2bb9ce6a79 100644 --- a/jdk/test/java/util/Arrays/ArraysEqCmpTest.java +++ b/jdk/test/java/util/Arrays/ArraysEqCmpTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8033148 + * @bug 8033148 8141409 * @summary tests for array equals and compare * @run testng ArraysEqCmpTest */ @@ -312,6 +312,8 @@ public class ArraysEqCmpTest { return Integer.compare(b, a); }; + final MethodHandle eqc; + final MethodHandle eqcr; final MethodHandle cmpc; final MethodHandle cmpcr; final MethodHandle mismatchc; @@ -327,6 +329,8 @@ public class ArraysEqCmpTest { int.class, Object[].class, int.class, int.class, Object[].class, int.class, int.class, Comparator.class); + eqc = l.findStatic(Arrays.class, "equals", cmpt.changeReturnType(boolean.class)); + eqcr = l.findStatic(Arrays.class, "equals", cmprt.changeReturnType(boolean.class)); cmpc = l.findStatic(Arrays.class, "compare", cmpt); cmpcr = l.findStatic(Arrays.class, "compare", cmprt); mismatchc = l.findStatic(Arrays.class, "mismatch", cmpt); @@ -337,6 +341,33 @@ public class ArraysEqCmpTest { } } + @Override + boolean equals(Object a, Object b) { + try { + return (boolean) eqc.invoke(a, b, c); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + + @Override + boolean equals(Object a, int aFromIndex, int aToIndex, + Object b, int bFromIndex, int bToIndex) { + try { + return (boolean) eqcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c); + } + catch (RuntimeException | Error e) { + throw e; + } + catch (Throwable t) { + throw new Error(t); + } + } + @Override int compare(Object a, Object b) { try { @@ -1002,10 +1033,12 @@ public class ArraysEqCmpTest { continue; if (o3 == null) { + testNPE(() -> Arrays.equals(o1, o2, o3)); testNPE(() -> Arrays.compare(o1, o2, o3)); testNPE(() -> Arrays.mismatch(o1, o2, o3)); } + testNPE(() -> Arrays.equals(o1, 0, 0, o2, 0, 0, o3)); testNPE(() -> Arrays.compare(o1, 0, 0, o2, 0, 0, o3)); testNPE(() -> Arrays.mismatch(o1, 0, 0, o2, 0, 0, o3)); }