--- a/jdk/src/java.base/share/classes/java/util/Arrays.java Wed Nov 04 12:46:05 2015 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java Wed Nov 04 16:44:38 2015 +0100
@@ -25,6 +25,8 @@
package java.util;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
@@ -42,7 +44,6 @@
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import jdk.internal.HotSpotIntrinsicCandidate;
/**
* This class contains various methods for manipulating arrays (such as
@@ -2586,6 +2587,55 @@
}
/**
+ * Returns true if the two specified arrays of longs, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ 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 (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of ints are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2615,6 +2665,55 @@
}
/**
+ * Returns true if the two specified arrays of ints, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ 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 (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of shorts are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2644,6 +2743,55 @@
}
/**
+ * Returns true if the two specified arrays of shorts, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ 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 (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of chars are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2674,6 +2822,55 @@
}
/**
+ * Returns true if the two specified arrays of chars, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(char[] a, int aFromIndex, int aToIndex,
+ char[] b, int bFromIndex, int bToIndex) {
+ 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 (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of bytes are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2703,6 +2900,55 @@
}
/**
+ * Returns true if the two specified arrays of bytes, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ 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 (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of booleans are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2732,6 +2978,55 @@
}
/**
+ * Returns true if the two specified arrays of booleans, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(boolean[] a, int aFromIndex, int aToIndex,
+ boolean[] b, int bFromIndex, int bToIndex) {
+ 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 (a[aFromIndex++] != b[bFromIndex++])
+ return false;
+
+ return true;
+ }
+
+ /**
* Returns {@code true} if the two specified arrays of doubles are
* <i>equal</i> to one another. Two arrays are considered equal if both
* arrays contain the same number of elements, and all corresponding pairs
@@ -2759,9 +3054,70 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (Double.doubleToLongBits(a[i])!=Double.doubleToLongBits(a2[i]))
- return false;
+ for (int i=0; i<length; i++) {
+ double v1 = a[i], v2 = a2[i];
+ if (Double.doubleToRawLongBits(v1) != Double.doubleToRawLongBits(v2))
+ if (!Double.isNaN(v1) || !Double.isNaN(v2))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the two specified arrays of doubles, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * <p>Two doubles {@code d1} and {@code d2} are considered equal if:
+ * <pre> {@code new Double(d1).equals(new Double(d2))}</pre>
+ * (Unlike the {@code ==} operator, this method considers
+ * {@code NaN} equals to itself, and 0.0d unequal to -0.0d.)
+ *
+ * @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
+ * @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 is {@code null}
+ * @see Double#equals(Object)
+ * @since 9
+ */
+ public static boolean equals(double[] a, int aFromIndex, int aToIndex,
+ double[] b, int bFromIndex, int bToIndex) {
+ 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++) {
+ Double va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
+ if (!Double.isNaN(va) || !Double.isNaN(vb))
+ return false;
+ }
return true;
}
@@ -2794,9 +3150,70 @@
if (a2.length != length)
return false;
- for (int i=0; i<length; i++)
- if (Float.floatToIntBits(a[i])!=Float.floatToIntBits(a2[i]))
- return false;
+ for (int i=0; i<length; i++) {
+ float v1 = a[i], v2 = a2[i];
+ if (Float.floatToRawIntBits(v1) != Float.floatToRawIntBits(v2))
+ if (!Float.isNaN(v1) || !Float.isNaN(v2))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the two specified arrays of floats, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * <p>Two floats {@code f1} and {@code f2} are considered equal if:
+ * <pre> {@code new Float(f1).equals(new Float(f2))}</pre>
+ * (Unlike the {@code ==} operator, this method considers
+ * {@code NaN} equals to itself, and 0.0f unequal to -0.0f.)
+ *
+ * @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
+ * @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 is {@code null}
+ * @see Float#equals(Object)
+ * @since 9
+ */
+ public static boolean equals(float[] a, int aFromIndex, int aToIndex,
+ float[] b, int bFromIndex, int bToIndex) {
+ 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++) {
+ float va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
+ if (!Float.isNaN(va) || !Float.isNaN(vb))
+ return false;
+ }
return true;
}
@@ -2827,9 +3244,60 @@
return false;
for (int i=0; i<length; i++) {
- Object o1 = a[i];
- Object o2 = a2[i];
- if (!(o1==null ? o2==null : o1.equals(o2)))
+ if (!Objects.equals(a[i], a2[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the two specified arrays of Objects, over the specified
+ * ranges, are <i>equal</i> to one another.
+ *
+ * <p>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.
+ *
+ * <p>Two objects {@code e1} and {@code e2} are considered <i>equal</i> if
+ * {@code Objects.equals(e1, e2)}.
+ *
+ * @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
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static boolean equals(Object[] a, int aFromIndex, int aToIndex,
+ Object[] b, int bFromIndex, int bToIndex) {
+ 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 (!Objects.equals(a[aFromIndex++], b[bFromIndex++]))
return false;
}
@@ -5185,4 +5653,3233 @@
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
}
-}
+
+
+ // Comparison methods
+
+ // Compare boolean
+
+ /**
+ * Compares two {@code boolean} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Boolean#compare(boolean, boolean)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(boolean[], boolean[])} for the definition of a
+ * common and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(boolean[], boolean[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Boolean.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(boolean[] a, boolean[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Boolean.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code boolean} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Boolean#compare(boolean, boolean)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(boolean[], int, int, boolean[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(boolean[], int, int, boolean[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Boolean.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(boolean[] a, int aFromIndex, int aToIndex,
+ boolean[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ boolean va = a[aFromIndex++];
+ boolean vb = b[bFromIndex++];
+ if (va != vb) return Boolean.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare byte
+
+ /**
+ * Compares two {@code byte} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Byte#compare(byte, byte)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(byte[], byte[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(byte[], byte[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Byte.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(byte[] a, byte[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Byte.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code byte} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Byte#compare(byte, byte)}, at a relative index
+ * within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(byte[], int, int, byte[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Byte.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ byte va = a[aFromIndex++];
+ byte vb = b[bFromIndex++];
+ if (va != vb) return Byte.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code byte} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Byte#compareUnsigned(byte, byte)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(byte[], byte[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Byte.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(byte[] a, byte[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Byte.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+
+ /**
+ * Compares two {@code byte} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Byte#compareUnsigned(byte, byte)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Byte.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is null
+ * @since 9
+ */
+ public static int compareUnsigned(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ byte va = a[aFromIndex++];
+ byte vb = b[bFromIndex++];
+ if (va != vb) return Byte.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare short
+
+ /**
+ * Compares two {@code short} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Short#compare(short, short)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(short[], short[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(short[], short[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Short.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(short[] a, short[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Short.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code short} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Short#compare(short, short)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(short[], int, int, short[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(short[], int, int, short[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Short.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ short va = a[aFromIndex++];
+ short vb = b[bFromIndex++];
+ if (va != vb) return Short.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code short} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Short#compareUnsigned(short, short)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(short[], short[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Short.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(short[] a, short[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Short.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code short} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Short#compareUnsigned(short, short)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(short[], int, int, short[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Short.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is null
+ * @since 9
+ */
+ public static int compareUnsigned(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ short va = a[aFromIndex++];
+ short vb = b[bFromIndex++];
+ if (va != vb) return Short.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare char
+
+ /**
+ * Compares two {@code char} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Character#compare(char, char)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(char[], char[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(char[], char[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Character.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(char[] a, char[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Character.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code char} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Character#compare(char, char)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(char[], int, int, char[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(char[], int, int, char[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Character.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(char[] a, int aFromIndex, int aToIndex,
+ char[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ char va = a[aFromIndex++];
+ char vb = b[bFromIndex++];
+ if (va != vb) return Character.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare int
+
+ /**
+ * Compares two {@code int} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Integer#compare(int, int)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(int[], int[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(int[], int[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Integer.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(int[] a, int[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Integer.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code int} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Integer#compare(int, int)}, at a relative index
+ * within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(int[], int, int, int[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(int[], int, int, int[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Integer.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ int va = a[aFromIndex++];
+ int vb = b[bFromIndex++];
+ if (va != vb) return Integer.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code int} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Integer#compareUnsigned(int, int)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(int[], int[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Integer.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(int[] a, int[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Integer.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code int} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Integer#compareUnsigned(int, int)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(int[], int, int, int[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Integer.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is null
+ * @since 9
+ */
+ public static int compareUnsigned(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ int va = a[aFromIndex++];
+ int vb = b[bFromIndex++];
+ if (va != vb) return Integer.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare long
+
+ /**
+ * Compares two {@code long} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Long#compare(long, long)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(long[], long[])} for the definition of a common and
+ * proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(long[], long[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Long.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(long[] a, long[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Long.compare(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code long} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Long#compare(long, long)}, at a relative index
+ * within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(long[], int, int, long[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(long[], int, int, long[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Long.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ long va = a[aFromIndex++];
+ long vb = b[bFromIndex++];
+ if (va != vb) return Long.compare(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code long} arrays lexicographically, numerically treating
+ * elements as unsigned.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Long#compareUnsigned(long, long)}, at an index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(long[], long[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Long.compareUnsigned(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are
+ * equal and contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compareUnsigned(long[] a, long[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return Long.compareUnsigned(a[i], b[i]);
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code long} arrays lexicographically over the specified
+ * ranges, numerically treating elements as unsigned.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Long#compareUnsigned(long, long)}, at a
+ * relative index within the respective arrays that is the length of the
+ * prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(long[], int, int, long[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Long.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is null
+ * @since 9
+ */
+ public static int compareUnsigned(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ long va = a[aFromIndex++];
+ long vb = b[bFromIndex++];
+ if (va != vb) return Long.compareUnsigned(va, vb);
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare float
+
+ /**
+ * Compares two {@code float} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Float#compare(float, float)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(float[], float[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(float[], float[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Float.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(float[] a, float[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ float va = a[i], vb = b[i];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) {
+ int c = Float.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code float} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Float#compare(float, float)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(float[], int, int, float[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(float[], int, int, float[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Float.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(float[] a, int aFromIndex, int aToIndex,
+ float[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ float va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb)) {
+ int c = Float.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare double
+
+ /**
+ * Compares two {@code double} arrays lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements, as if by
+ * {@link Double#compare(double, double)}, at an index within the respective
+ * arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(double[], double[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(double[], double[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return Double.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static int compare(double[] a, double[] b) {
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ double va = a[i], vb = b[i];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) {
+ int c = Double.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code double} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements, as if by {@link Double#compare(double, double)}, at a relative
+ * index within the respective arrays that is the length of the prefix.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(double[], int, int, double[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(double[], int, int, double[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if:
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return Double.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int compare(double[] a, int aFromIndex, int aToIndex,
+ double[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ double va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb)) {
+ int c = Double.compare(va, vb);
+ if (c != 0) return c;
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+ // Compare objects
+
+ /**
+ * Compares two {@code Object} arrays, within comparable elements,
+ * lexicographically.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing two elements of type {@code T} at
+ * an index {@code i} within the respective arrays that is the prefix
+ * length, as if by:
+ * <pre>{@code
+ * Comparator.nullsFirst(Comparator.<T>naturalOrder()).
+ * compare(a[i], b[i])
+ * }</pre>
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(Object[], Object[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ * A {@code null} array element is considered lexicographically than a
+ * non-{@code null} array element. Two {@code null} array elements are
+ * considered equal.
+ *
+ * <p>The comparison is consistent with {@link #equals(Object[], Object[]) equals},
+ * more specifically the following holds for arrays {@code a} and {@code b}:
+ * <pre>{@code
+ * Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references
+ * and elements):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return a[i].compareTo(b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @param <T> the type of comparable array elements
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @since 9
+ */
+ public static <T extends Comparable<? super T>> int compare(T[] a, T[] b) {
+ if (a == b)
+ return 0;
+ // A null array is less than a non-null array
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ T oa = a[i];
+ T ob = b[i];
+ if (oa != ob) {
+ // A null element is less than a non-null element
+ if (oa == null || ob == null)
+ return oa == null ? -1 : 1;
+ int v = oa.compareTo(ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code Object} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing two
+ * elements of type {@code T} at a relative index {@code i} within the
+ * respective arrays that is the prefix length, as if by:
+ * <pre>{@code
+ * Comparator.nullsFirst(Comparator.<T>naturalOrder()).
+ * compare(a[aFromIndex + i, b[bFromIndex + i])
+ * }</pre>
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * <p>The comparison is consistent with
+ * {@link #equals(Object[], int, int, Object[], int, int) equals}, more
+ * specifically the following holds for arrays {@code a} and {@code b} with
+ * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively:
+ * <pre>{@code
+ * Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+ * (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+ * }</pre>
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array elements):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return a[aFromIndex + i].compareTo(b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @param <T> the type of comparable array elements
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static <T extends Comparable<? super T>> int compare(
+ T[] a, int aFromIndex, int aToIndex,
+ T[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ T oa = a[aFromIndex++];
+ T ob = b[bFromIndex++];
+ if (oa != ob) {
+ if (oa == null || ob == null)
+ return oa == null ? -1 : 1;
+ int v = oa.compareTo(ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+ /**
+ * Compares two {@code Object} arrays lexicographically using a specified
+ * comparator.
+ *
+ * <p>If the two arrays share a common prefix then the lexicographic
+ * comparison is the result of comparing with the specified comparator two
+ * elements at an index within the respective arrays that is the prefix
+ * length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two array lengths.
+ * (See {@link #mismatch(Object[], Object[])} for the definition of a common
+ * and proper prefix.)
+ *
+ * <p>A {@code null} array reference is considered lexicographically less
+ * than a non-{@code null} array reference. Two {@code null} array
+ * references are considered equal.
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array references):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, b, cmp);
+ * if (i >= 0 && i < Math.min(a.length, b.length))
+ * return cmp.compare(a[i], b[i]);
+ * return a.length - b.length;
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param b the second array to compare
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the value {@code 0} if the first and second array are equal and
+ * contain the same elements in the same order;
+ * a value less than {@code 0} if the first array is
+ * lexicographically less than the second array; and
+ * a value greater than {@code 0} if the first array is
+ * lexicographically greater than the second array
+ * @throws NullPointerException if the comparator is {@code null}
+ * @since 9
+ */
+ public static <T> int compare(T[] a, T[] b,
+ Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ if (a == b)
+ return 0;
+ if (a == null || b == null)
+ return a == null ? -1 : 1;
+
+ int length = Math.min(a.length, b.length);
+ for (int i = 0; i < length; i++) {
+ T oa = a[i];
+ T ob = b[i];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return a.length - b.length;
+ }
+
+ /**
+ * Compares two {@code Object} arrays lexicographically over the specified
+ * ranges.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the lexicographic comparison is the result of comparing with the
+ * specified comparator two elements at a relative index within the
+ * respective arrays that is the prefix length.
+ * Otherwise, one array is a proper prefix of the other and, lexicographic
+ * comparison is the result of comparing the two range lengths.
+ * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the
+ * definition of a common and proper prefix.)
+ *
+ * @apiNote
+ * <p>This method behaves as if (for non-{@code null} array elements):
+ * <pre>{@code
+ * int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+ * b, bFromIndex, bToIndex, cmp);
+ * if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * return cmp.compare(a[aFromIndex + i], b[bFromIndex + i]);
+ * return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+ * }</pre>
+ *
+ * @param a the first array to compare
+ * @param aFromIndex the index (inclusive) of the first element in the
+ * first array to be compared
+ * @param aToIndex the index (exclusive) of the last element in the
+ * first array to be compared
+ * @param b the second array to compare
+ * @param bFromIndex the index (inclusive) of the first element in the
+ * second array to be compared
+ * @param bToIndex the index (exclusive) of the last element in the
+ * second array to be compared
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the value {@code 0} if, over the specified ranges, the first and
+ * second array are equal and contain the same elements in the same
+ * order;
+ * a value less than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically less than the second array; and
+ * a value greater than {@code 0} if, over the specified ranges, the
+ * first array is lexicographically greater than the second array
+ * @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 <T> int compare(
+ T[] a, int aFromIndex, int aToIndex,
+ T[] b, int bFromIndex, int bToIndex,
+ Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ T oa = a[aFromIndex++];
+ T ob = b[bFromIndex++];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return v;
+ }
+ }
+ }
+
+ return aLength - bLength;
+ }
+
+
+ // Mismatch methods
+
+ // Mismatch boolean
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code boolean} arrays, otherwise return -1 if no mismatch is found. The
+ * index will be in the range of 0 (inclusive) up to the length (inclusive)
+ * of the smaller array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(boolean[] a, boolean[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code boolean} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(boolean[] a, int aFromIndex, int aToIndex,
+ boolean[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch byte
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code byte}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(byte[] a, byte[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code byte} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(byte[] a, int aFromIndex, int aToIndex,
+ byte[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch char
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code char}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(char[] a, char[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code char} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(char[] a, int aFromIndex, int aToIndex,
+ char[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch short
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code short}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(short[] a, short[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code short} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(short[] a, int aFromIndex, int aToIndex,
+ short[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch int
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code int}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(int[] a, int[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code int} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(int[] a, int aFromIndex, int aToIndex,
+ int[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch long
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code long}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * a[pl] != b[pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(long[] a, long[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (a[i] != b[i]) return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code long} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * a[aFromIndex + pl] != b[bFromIndex + pl]
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(long[] a, int aFromIndex, int aToIndex,
+ long[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (a[aFromIndex++] != b[bFromIndex++]) return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch float
+
+ /**
+ * Finds and returns the index of the first mismatch between two {@code float}
+ * arrays, otherwise return -1 if no mismatch is found. The index will be
+ * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+ * array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * Float.compare(a[pl], b[pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(float[] a, float[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ float va = a[i], vb = b[i];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
+ if (!Float.isNaN(va) || !Float.isNaN(vb))
+ return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code float} arrays over the specified ranges, otherwise return -1 if no
+ * mismatch is found. The index will be in the range of 0 (inclusive) up to
+ * the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * Float.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(float[] a, int aFromIndex, int aToIndex,
+ float[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ float va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Float.floatToRawIntBits(va) != Float.floatToRawIntBits(vb))
+ if (!Float.isNaN(va) || !Float.isNaN(vb))
+ return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch double
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code double} arrays, otherwise return -1 if no mismatch is found. The
+ * index will be in the range of 0 (inclusive) up to the length (inclusive)
+ * of the smaller array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * Double.compare(a[pl], b[pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(double[] a, double[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ double va = a[i], vb = b[i];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
+ if (!Double.isNaN(va) || !Double.isNaN(vb))
+ return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code double} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * Double.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(double[] a, int aFromIndex, int aToIndex,
+ double[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ double va = a[aFromIndex++], vb = b[bFromIndex++];
+ if (Double.doubleToRawLongBits(va) != Double.doubleToRawLongBits(vb))
+ if (!Double.isNaN(va) || !Double.isNaN(vb))
+ return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ // Mismatch objects
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code Object} arrays, otherwise return -1 if no mismatch is found. The
+ * index will be in the range of 0 (inclusive) up to the length (inclusive)
+ * of the smaller array.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(a.length, b.length) &&
+ * Arrays.equals(a, 0, pl, b, 0, pl) &&
+ * !Objects.equals(a[pl], b[pl])
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@code
+ * a.length != b.length &&
+ * Arrays.equals(a, 0, Math.min(a.length, b.length),
+ * b, 0, Math.min(a.length, b.length))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array is {@code null}
+ * @since 9
+ */
+ public static int mismatch(Object[] a, Object[] b) {
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ if (!Objects.equals(a[i], b[i]))
+ return i;
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code Object} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@code
+ * pl >= 0 &&
+ * pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+ * Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+ * !Objects.equals(a[aFromIndex + pl], b[bFromIndex + pl])
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@code
+ * (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+ * Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+ * b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 is {@code null}
+ * @since 9
+ */
+ public static int mismatch(
+ Object[] a, int aFromIndex, int aToIndex,
+ Object[] b, int bFromIndex, int bToIndex) {
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ if (!Objects.equals(a[aFromIndex++], b[bFromIndex++]))
+ return i;
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+
+ /**
+ * Finds and returns the index of the first mismatch between two
+ * {@code Object} arrays, otherwise return -1 if no mismatch is found.
+ * The index will be in the range of 0 (inclusive) up to the length
+ * (inclusive) of the smaller array.
+ *
+ * <p>The specified comparator is used to determine if two array elements
+ * from the each array are not equal.
+ *
+ * <p>If the two arrays share a common prefix then the returned index is the
+ * length of the common prefix and it follows that there is a mismatch
+ * between the two elements at that index within the respective arrays.
+ * If one array is a proper prefix of the other then the returned index is
+ * the length of the smaller array and it follows that the index is only
+ * valid for the larger array.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@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) &&
+ * cmp.compare(a[pl], b[pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+ * prefix if the following expression is true:
+ * <pre>{@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) &&
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @param b the second array to be tested for a mismatch
+ * @param cmp the comparator to compare array elements
+ * @param <T> the type of array elements
+ * @return the index of the first mismatch between the two arrays,
+ * otherwise {@code -1}.
+ * @throws NullPointerException
+ * if either array or the comparator is {@code null}
+ * @since 9
+ */
+ public static <T> int mismatch(T[] a, T[] b, Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ int length = Math.min(a.length, b.length); // Check null array refs
+ if (a == b)
+ return -1;
+
+ for (int i = 0; i < length; i++) {
+ T oa = a[i];
+ T ob = b[i];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return i;
+ }
+ }
+ }
+
+ return a.length != b.length ? length : -1;
+ }
+
+ /**
+ * Finds and returns the relative index of the first mismatch between two
+ * {@code Object} arrays over the specified ranges, otherwise return -1 if
+ * no mismatch is found. The index will be in the range of 0 (inclusive) up
+ * to the length (inclusive) of the smaller range.
+ *
+ * <p>If the two arrays, over the specified ranges, share a common prefix
+ * then the returned relative index is the length of the common prefix and
+ * it follows that there is a mismatch between the two elements at that
+ * relative index within the respective arrays.
+ * If one array is a proper prefix of the other, over the specified ranges,
+ * then the returned relative index is the length of the smaller range and
+ * it follows that the relative index is only valid for the array with the
+ * larger range.
+ * Otherwise, there is no mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+ * prefix of length {@code pl} if the following expression is true:
+ * <pre>{@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) &&
+ * cmp.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+ * }</pre>
+ * Note that a common prefix length of {@code 0} indicates that the first
+ * elements from each array mismatch.
+ *
+ * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+ * ranges [{@code aFromIndex}, {@code atoIndex}) and
+ * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+ * if the following expression is true:
+ * <pre>{@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)
+ * }</pre>
+ *
+ * @param a the first array to be tested for a mismatch
+ * @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 for a mismatch
+ * @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 <T> the type of array elements
+ * @return the relative index of the first mismatch between the two arrays
+ * over the specified ranges, otherwise {@code -1}.
+ * @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 <T> int mismatch(
+ T[] a, int aFromIndex, int aToIndex,
+ T[] b, int bFromIndex, int bToIndex,
+ Comparator<? super T> cmp) {
+ Objects.requireNonNull(cmp);
+ rangeCheck(a.length, aFromIndex, aToIndex);
+ rangeCheck(b.length, bFromIndex, bToIndex);
+
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ int length = Math.min(aLength, bLength);
+ for (int i = 0; i < length; i++) {
+ T oa = a[aFromIndex++];
+ T ob = b[bFromIndex++];
+ if (oa != ob) {
+ // Null-value comparison is deferred to the comparator
+ int v = cmp.compare(oa, ob);
+ if (v != 0) {
+ return i;
+ }
+ }
+ }
+
+ return aLength != bLength ? length : -1;
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Arrays/ArraysEqCmpTest.java Wed Nov 04 16:44:38 2015 +0100
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8033148
+ * @summary tests for array equals and compare
+ * @run testng ArraysEqCmpTest
+*/
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.LongFunction;
+import java.util.stream.IntStream;
+
+public class ArraysEqCmpTest {
+
+ // Maximum width in bits
+ static final int MAX_WIDTH = 512;
+
+ static final Map<Class, Integer> typeToWidth;
+
+ static {
+ typeToWidth = new HashMap<>();
+ typeToWidth.put(boolean.class, Byte.SIZE);
+ typeToWidth.put(byte.class, Byte.SIZE);
+ typeToWidth.put(short.class, Short.SIZE);
+ typeToWidth.put(char.class, Character.SIZE);
+ typeToWidth.put(int.class, Integer.SIZE);
+ typeToWidth.put(long.class, Long.SIZE);
+ typeToWidth.put(float.class, Float.SIZE);
+ typeToWidth.put(double.class, Double.SIZE);
+ typeToWidth.put(Object.class, Integer.SIZE); // @@@ 32 or 64?
+ }
+
+ static int arraySizeFor(Class<?> type) {
+ type = type.isPrimitive() ? type : Object.class;
+ return 4 * MAX_WIDTH / typeToWidth.get(type);
+ }
+
+ static abstract class ArrayType<T> {
+ final Class<?> arrayType;
+ final Class<?> componentType;
+ final boolean unsigned;
+
+ final MethodHandle cpy;
+
+ final MethodHandle eq;
+ final MethodHandle eqr;
+ final MethodHandle cmp;
+ final MethodHandle cmpr;
+ final MethodHandle mm;
+ final MethodHandle mmr;
+
+ final MethodHandle getter;
+
+ final MethodHandle toString;
+
+ public ArrayType(Class<T> arrayType) {
+ this(arrayType, false);
+ }
+
+ public ArrayType(Class<T> arrayType, boolean unsigned) {
+ this.arrayType = arrayType;
+ this.componentType = arrayType.getComponentType();
+ this.unsigned = unsigned;
+
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+
+ getter = MethodHandles.arrayElementGetter(arrayType);
+
+ if (componentType.isPrimitive()) {
+ cpy = l.findStatic(Arrays.class, "copyOfRange",
+ MethodType.methodType(arrayType, arrayType, int.class, int.class));
+
+ MethodType eqt = MethodType.methodType(
+ boolean.class, arrayType, arrayType);
+ MethodType eqrt = MethodType.methodType(
+ boolean.class, arrayType, int.class, int.class, arrayType, int.class, int.class);
+
+ eq = l.findStatic(Arrays.class, "equals", eqt);
+ eqr = l.findStatic(Arrays.class, "equals", eqrt);
+
+ String compareName = unsigned ? "compareUnsigned" : "compare";
+ cmp = l.findStatic(Arrays.class, compareName,
+ eqt.changeReturnType(int.class));
+ cmpr = l.findStatic(Arrays.class, compareName,
+ eqrt.changeReturnType(int.class));
+
+ mm = l.findStatic(Arrays.class, "mismatch",
+ eqt.changeReturnType(int.class));
+ mmr = l.findStatic(Arrays.class, "mismatch",
+ eqrt.changeReturnType(int.class));
+
+ toString = l.findStatic(Arrays.class, "toString",
+ MethodType.methodType(String.class, arrayType));
+ }
+ else {
+ cpy = l.findStatic(Arrays.class, "copyOfRange",
+ MethodType.methodType(Object[].class, Object[].class, int.class, int.class));
+
+ MethodType eqt = MethodType.methodType(
+ boolean.class, Object[].class, Object[].class);
+ MethodType eqrt = MethodType.methodType(
+ boolean.class, Object[].class, int.class, int.class, Object[].class, int.class, int.class);
+
+ eq = l.findStatic(Arrays.class, "equals", eqt);
+ eqr = l.findStatic(Arrays.class, "equals", eqrt);
+
+ MethodType cmpt = MethodType.methodType(
+ int.class, Comparable[].class, Comparable[].class);
+ MethodType cmprt = MethodType.methodType(
+ int.class, Comparable[].class, int.class, int.class, Comparable[].class, int.class, int.class);
+
+ cmp = l.findStatic(Arrays.class, "compare", cmpt);
+ cmpr = l.findStatic(Arrays.class, "compare", cmprt);
+
+ mm = l.findStatic(Arrays.class, "mismatch",
+ eqt.changeReturnType(int.class));
+ mmr = l.findStatic(Arrays.class, "mismatch",
+ eqrt.changeReturnType(int.class));
+
+ toString = l.findStatic(Arrays.class, "toString",
+ MethodType.methodType(String.class, Object[].class));
+ }
+
+ }
+ catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String s = arrayType.getCanonicalName();
+ return unsigned ? "unsigned " + s : s;
+ }
+
+ Object construct(int length) {
+ return Array.newInstance(componentType, length);
+ }
+
+ Object copyOf(Object a) {
+ return copyOf(a, 0, Array.getLength(a));
+ }
+
+ Object copyOf(Object a, int from, int to) {
+ try {
+ return (Object) cpy.invoke(a, from, to);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ Object get(Object a, int i) {
+ try {
+ return (Object) getter.invoke(a, i);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ abstract void set(Object a, int i, Object v);
+
+ boolean equals(Object a, Object b) {
+ try {
+ return (boolean) eq.invoke(a, b);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ boolean equals(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (boolean) eqr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int compare(Object a, Object b) {
+ try {
+ return (int) cmp.invoke(a, b);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int compare(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) cmpr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int mismatch(Object a, Object b) {
+ try {
+ return (int) mm.invoke(a, b);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ int mismatch(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) mmr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ String toString(Object a) {
+ try {
+ return (String) toString.invoke(a);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ static class BoxedIntegers extends ArrayType<Integer[]> {
+ public BoxedIntegers() {
+ super(Integer[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ // Ensure unique reference
+ ((Integer[]) a)[i] = v != null ? new Integer((Integer) v) : null;
+ }
+ }
+
+ static class BoxedIntegersWithReverseComparator extends BoxedIntegers {
+ final Comparator<Integer> c = (a, b) -> {
+ // Nulls sort after non-nulls
+ if (a == null || b == null)
+ return a == null ? b == null ? 0 : 1 : -1;
+
+ return Integer.compare(b, a);
+ };
+
+ final MethodHandle cmpc;
+ final MethodHandle cmpcr;
+ final MethodHandle mismatchc;
+ final MethodHandle mismatchcr;
+
+ public BoxedIntegersWithReverseComparator() {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+
+ MethodType cmpt = MethodType.methodType(
+ int.class, Object[].class, Object[].class, Comparator.class);
+ MethodType cmprt = MethodType.methodType(
+ int.class, Object[].class, int.class, int.class,
+ Object[].class, int.class, int.class, Comparator.class);
+
+ cmpc = l.findStatic(Arrays.class, "compare", cmpt);
+ cmpcr = l.findStatic(Arrays.class, "compare", cmprt);
+ mismatchc = l.findStatic(Arrays.class, "mismatch", cmpt);
+ mismatchcr = l.findStatic(Arrays.class, "mismatch", cmprt);
+ }
+ catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ @Override
+ int compare(Object a, Object b) {
+ try {
+ return (int) cmpc.invoke(a, b, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ int compare(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) cmpcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ int mismatch(Object a, Object b) {
+ try {
+ return (int) mismatchc.invoke(a, b, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ int mismatch(Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ try {
+ return (int) mismatchcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+ }
+ catch (RuntimeException | Error e) {
+ throw e;
+ }
+ catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return arrayType.getCanonicalName() + " with Comparator";
+ }
+ }
+
+ static class Booleans extends ArrayType<boolean[]> {
+ public Booleans() {
+ super(boolean[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ boolean pv;
+ if (v instanceof Boolean) {
+ pv = (Boolean) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v) >= 0;
+ }
+ else throw new IllegalStateException();
+
+ ((boolean[]) a)[i] = pv;
+ }
+ }
+
+ static class Bytes extends ArrayType<byte[]> {
+ public Bytes(boolean unsigned) {
+ super(byte[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ byte pv;
+ if (v instanceof Byte) {
+ pv = (Byte) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).byteValue();
+ }
+ else throw new IllegalStateException();
+
+ ((byte[]) a)[i] = pv;
+ }
+ }
+
+ static class Characters extends ArrayType<char[]> {
+ public Characters() {
+ super(char[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ char pv;
+ if (v instanceof Character) {
+ pv = (Character) v;
+ }
+ else if (v instanceof Integer) {
+ pv = (char) ((Integer) v).intValue();
+ }
+ else throw new IllegalStateException();
+
+ ((char[]) a)[i] = pv;
+ }
+ }
+
+ static class Shorts extends ArrayType<short[]> {
+ public Shorts(boolean unsigned) {
+ super(short[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ short pv;
+ if (v instanceof Short) {
+ pv = (Short) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).shortValue();
+ }
+ else throw new IllegalStateException();
+
+ ((short[]) a)[i] = pv;
+ }
+ }
+
+ static class Integers extends ArrayType<int[]> {
+ public Integers(boolean unsigned) {
+ super(int[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ int pv;
+ if (v instanceof Integer) {
+ pv = ((Integer) v).shortValue();
+ }
+ else throw new IllegalStateException();
+
+ ((int[]) a)[i] = pv;
+ }
+ }
+
+ static class Longs extends ArrayType<long[]> {
+ public Longs(boolean unsigned) {
+ super(long[].class, unsigned);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ long pv;
+ if (v instanceof Long) {
+ pv = (Long) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).longValue();
+ }
+ else throw new IllegalStateException();
+
+ ((long[]) a)[i] = pv;
+ }
+ }
+
+ static class Floats extends ArrayType<float[]> {
+ public Floats() {
+ super(float[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ float pv;
+ if (v instanceof Float) {
+ pv = (Float) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).floatValue();
+ }
+ else throw new IllegalStateException();
+
+ ((float[]) a)[i] = pv;
+ }
+ }
+
+ static class Doubles extends ArrayType<double[]> {
+ public Doubles() {
+ super(double[].class);
+ }
+
+ @Override
+ void set(Object a, int i, Object v) {
+ double pv;
+ if (v instanceof Double) {
+ pv = (Double) v;
+ }
+ else if (v instanceof Integer) {
+ pv = ((Integer) v).doubleValue();
+ }
+ else throw new IllegalStateException();
+
+ ((double[]) a)[i] = pv;
+ }
+ }
+ }
+
+ static Object[][] arrayTypes;
+
+ @DataProvider
+ public static Object[][] arrayTypesProvider() {
+ if (arrayTypes == null) {
+ arrayTypes = new Object[][]{
+ new Object[]{new ArrayType.BoxedIntegers()},
+ new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
+ new Object[]{new ArrayType.Booleans()},
+ new Object[]{new ArrayType.Bytes(false)},
+ new Object[]{new ArrayType.Bytes(true)},
+ new Object[]{new ArrayType.Characters()},
+ new Object[]{new ArrayType.Shorts(false)},
+ new Object[]{new ArrayType.Shorts(true)},
+ new Object[]{new ArrayType.Integers(false)},
+ new Object[]{new ArrayType.Integers(true)},
+ new Object[]{new ArrayType.Longs(false)},
+ new Object[]{new ArrayType.Longs(true)},
+ new Object[]{new ArrayType.Floats()},
+ new Object[]{new ArrayType.Doubles()},
+ };
+ }
+ return arrayTypes;
+ }
+
+ static Object[][] floatArrayTypes;
+
+ @DataProvider
+ public static Object[][] floatArrayTypesProvider() {
+ if (floatArrayTypes == null) {
+ LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
+ LongFunction<Object> bToD = Double::longBitsToDouble;
+
+ floatArrayTypes = new Object[][]{
+ new Object[]{new ArrayType.Floats(), 0x7fc00000L, 0x7f800001L, bTof},
+ new Object[]{new ArrayType.Doubles(), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD},
+ };
+ }
+ return floatArrayTypes;
+ }
+
+ static Object[][] objectArrayTypes;
+
+ @DataProvider
+ public static Object[][] objectArrayTypesProvider() {
+ if (objectArrayTypes == null) {
+ LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
+ LongFunction<Object> bToD = Double::longBitsToDouble;
+
+ objectArrayTypes = new Object[][]{
+ new Object[]{new ArrayType.BoxedIntegers()},
+ new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
+ };
+ }
+ return objectArrayTypes;
+ }
+
+
+ static Object[][] signedUnsignedArrayTypes;
+
+ @DataProvider
+ public static Object[][] signedUnsignedArrayTypes() {
+ if (signedUnsignedArrayTypes == null) {
+ signedUnsignedArrayTypes = new Object[][]{
+ new Object[]{new ArrayType.Bytes(false), new ArrayType.Bytes(true)},
+ new Object[]{new ArrayType.Shorts(false), new ArrayType.Shorts(true)},
+ new Object[]{new ArrayType.Integers(false), new ArrayType.Integers(true)},
+ new Object[]{new ArrayType.Longs(false), new ArrayType.Longs(true)},
+ };
+ }
+ return signedUnsignedArrayTypes;
+ }
+
+ // Equality and comparison tests
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testArray(ArrayType<?> arrayType) {
+ BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, x % 8);
+ }
+ return a;
+ };
+
+ BiFunction<ArrayType<?>, Object, Object> cloner = (at, a) ->
+ constructor.apply(at, Array.getLength(a));
+
+ testArrayType(arrayType, constructor, cloner);
+ }
+
+ @Test(dataProvider = "floatArrayTypesProvider")
+ public void testPrimitiveFloatArray(
+ ArrayType<?> arrayType,
+ long canonicalNanRawBits, long nonCanonicalNanRawBits,
+ LongFunction<Object> bitsToFloat) {
+ Object canonicalNan = bitsToFloat.apply(canonicalNanRawBits);
+ // If conversion is a signalling NaN it may be subject to conversion to a
+ // quiet NaN on some processors, even if a copy is performed
+ // The tests assume that if conversion occurs it does not convert to the
+ // canonical NaN
+ Object nonCanonicalNan = bitsToFloat.apply(nonCanonicalNanRawBits);
+
+ BiFunction<ArrayType<?>, Integer, Object> canonicalNaNs = (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, canonicalNan);
+ }
+ return a;
+ };
+
+ BiFunction<ArrayType<?>, Object, Object> nonCanonicalNaNs = (at, a) -> {
+ int s = Array.getLength(a);
+ Object ac = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(ac, x, nonCanonicalNan);
+ }
+ return ac;
+ };
+
+ BiFunction<ArrayType<?>, Object, Object> halfNonCanonicalNaNs = (at, a) -> {
+ int s = Array.getLength(a);
+ Object ac = at.construct(s);
+ for (int x = 0; x < s / 2; x++) {
+ at.set(ac, x, nonCanonicalNan);
+ }
+ for (int x = s / 2; x < s; x++) {
+ at.set(ac, x, 1);
+ }
+ return ac;
+ };
+
+ testArrayType(arrayType, canonicalNaNs, nonCanonicalNaNs);
+ testArrayType(arrayType, canonicalNaNs, halfNonCanonicalNaNs);
+ }
+
+ @Test(dataProvider = "objectArrayTypesProvider")
+ public void testNullElementsInObjectArray(ArrayType<?> arrayType) {
+ BiFunction<ArrayType<?>, Object, Object> cloner = ArrayType::copyOf;
+
+ // All nulls
+ testArrayType(arrayType,
+ (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, null);
+ }
+ return a;
+ },
+ cloner);
+
+
+ // Some nulls
+ testArrayType(arrayType,
+ (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ int v = x % 8;
+ at.set(a, x, v == 0 ? null : v);
+ }
+ return a;
+ },
+ cloner);
+
+ Integer[] a = new Integer[]{null, 0};
+ Integer[] b = new Integer[]{0, 0};
+ Assert.assertTrue(Arrays.compare(a, b) < 0);
+ Assert.assertTrue(Arrays.compare(b, a) > 0);
+ }
+
+ @Test(dataProvider = "objectArrayTypesProvider")
+ public void testSameRefElementsInObjectArray(ArrayType<?> arrayType) {
+ BiFunction<ArrayType<?>, Object, Object> cloner = ArrayType::copyOf;
+
+ // One ref
+ Integer one = 1;
+ testArrayType(arrayType,
+ (at, s) -> {
+ Integer[] a = (Integer[]) at.construct(s);
+ for (int x = 0; x < s; x++) {
+ a[x] = one;
+ }
+ return a;
+ },
+ cloner);
+
+ // All ref
+ testArrayType(arrayType,
+ (at, s) -> {
+ Integer[] a = (Integer[]) at.construct(s);
+ for (int x = 0; x < s; x++) {
+ a[x] = Integer.valueOf(s);
+ }
+ return a;
+ },
+ cloner);
+
+ // Some same ref
+ testArrayType(arrayType,
+ (at, s) -> {
+ Integer[] a = (Integer[]) at.construct(s);
+ for (int x = 0; x < s; x++) {
+ int v = x % 8;
+ a[x] = v == 1 ? one : new Integer(v);
+ }
+ return a;
+ },
+ cloner);
+ }
+
+ @Test(dataProvider = "signedUnsignedArrayTypes")
+ public void testSignedUnsignedArray(ArrayType<?> sat, ArrayType<?> uat) {
+ BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
+ Object a = at.construct(s);
+ for (int x = 0; x < s; x++) {
+ at.set(a, x, 1);
+ }
+ return a;
+ };
+
+ int n = arraySizeFor(sat.componentType);
+
+ for (int s : ranges(0, n)) {
+ Object a = constructor.apply(sat, s);
+
+ for (int aFrom : ranges(0, s)) {
+ for (int aTo : ranges(aFrom, s)) {
+ int aLength = aTo - aFrom;
+
+ if (aLength > 0) {
+ for (int i = aFrom; i < aTo; i++) {
+ Object ac = sat.copyOf(a);
+ // Create common prefix with a length of i - aFrom
+ sat.set(ac, i, -1);
+
+ int sc = sat.compare(ac, aFrom, aTo, a, aFrom, aTo);
+ int uc = uat.compare(ac, aFrom, aTo, a, aFrom, aTo);
+
+ Assert.assertTrue(sc < 0);
+ Assert.assertTrue(uc > 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void testArrayType(ArrayType<?> at,
+ BiFunction<ArrayType<?>, Integer, Object> constructor,
+ BiFunction<ArrayType<?>, Object, Object> cloner) {
+ int n = arraySizeFor(at.componentType);
+
+ for (int s : ranges(0, n)) {
+ Object a = constructor.apply(at, s);
+ Object b = cloner.apply(at, a);
+
+ for (int aFrom : ranges(0, s)) {
+ for (int aTo : ranges(aFrom, s)) {
+ int aLength = aTo - aFrom;
+
+ for (int bFrom : ranges(0, s)) {
+ for (int bTo : ranges(bFrom, s)) {
+ int bLength = bTo - bFrom;
+
+ Object anr = at.copyOf(a, aFrom, aTo);
+ Object bnr = at.copyOf(b, bFrom, bTo);
+
+ boolean eq = isEqual(at, a, aFrom, aTo, b, bFrom, bTo);
+ Assert.assertEquals(at.equals(a, aFrom, aTo, b, bFrom, bTo), eq);
+ Assert.assertEquals(at.equals(b, bFrom, bTo, a, aFrom, aTo), eq);
+ Assert.assertEquals(at.equals(anr, bnr), eq);
+ Assert.assertEquals(at.equals(bnr, anr), eq);
+ if (eq) {
+ Assert.assertEquals(at.compare(a, aFrom, aTo, b, bFrom, bTo), 0);
+ Assert.assertEquals(at.compare(b, bFrom, bTo, a, aFrom, aTo), 0);
+ Assert.assertEquals(at.compare(anr, bnr), 0);
+ Assert.assertEquals(at.compare(bnr, anr), 0);
+
+ Assert.assertEquals(at.mismatch(a, aFrom, aTo, b, bFrom, bTo), -1);
+ Assert.assertEquals(at.mismatch(b, bFrom, bTo, a, aFrom, aTo), -1);
+ Assert.assertEquals(at.mismatch(anr, bnr), -1);
+ Assert.assertEquals(at.mismatch(bnr, anr), -1);
+ }
+ else {
+ int aCb = at.compare(a, aFrom, aTo, b, bFrom, bTo);
+ int bCa = at.compare(b, bFrom, bTo, a, aFrom, aTo);
+ int v = Integer.signum(aCb) * Integer.signum(bCa);
+ Assert.assertTrue(v == -1);
+
+ int anrCbnr = at.compare(anr, bnr);
+ int bnrCanr = at.compare(bnr, anr);
+ Assert.assertEquals(anrCbnr, aCb);
+ Assert.assertEquals(bnrCanr, bCa);
+
+
+ int aMb = at.mismatch(a, aFrom, aTo, b, bFrom, bTo);
+ int bMa = at.mismatch(b, bFrom, bTo, a, aFrom, aTo);
+ int anrMbnr = at.mismatch(anr, bnr);
+ int bnrManr = at.mismatch(bnr, anr);
+
+ Assert.assertNotEquals(aMb, -1);
+ Assert.assertEquals(aMb, bMa);
+ Assert.assertNotEquals(anrMbnr, -1);
+ Assert.assertEquals(anrMbnr, bnrManr);
+ Assert.assertEquals(aMb, anrMbnr);
+ Assert.assertEquals(bMa, bnrManr);
+
+ // Common or proper prefix
+ Assert.assertTrue(at.equals(a, aFrom, aFrom + aMb, b, bFrom, bFrom + aMb));
+ if (aMb < Math.min(aLength, bLength)) {
+ // Common prefix
+ Assert.assertFalse(isEqual(at, a, aFrom + aMb, b, bFrom + aMb));
+ }
+ }
+ }
+ }
+
+ if (aLength > 0) {
+ for (int i = aFrom; i < aTo; i++) {
+ Object ac = at.copyOf(a);
+ // Create common prefix with a length of i - aFrom
+ at.set(ac, i, -1);
+
+ Object acnr = at.copyOf(ac, aFrom, aTo);
+ Object anr = at.copyOf(a, aFrom, aTo);
+
+ Assert.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo));
+ Assert.assertFalse(at.equals(acnr, anr));
+
+ int acCa = at.compare(ac, aFrom, aTo, a, aFrom, aTo);
+ int aCac = at.compare(a, aFrom, aTo, ac, aFrom, aTo);
+ int v = Integer.signum(acCa) * Integer.signum(aCac);
+ Assert.assertTrue(v == -1);
+
+ int acnrCanr = at.compare(acnr, anr);
+ int anrCacnr = at.compare(anr, acnr);
+ Assert.assertEquals(acnrCanr, acCa);
+ Assert.assertEquals(anrCacnr, aCac);
+
+
+ int acMa = at.mismatch(ac, aFrom, aTo, a, aFrom, aTo);
+ int aMac = at.mismatch(a, aFrom, aTo, ac, aFrom, aTo);
+ Assert.assertEquals(acMa, aMac);
+ Assert.assertEquals(acMa, i - aFrom);
+
+ int acnrManr = at.mismatch(acnr, anr);
+ int anrMacnr = at.mismatch(anr, acnr);
+ Assert.assertEquals(acnrManr, anrMacnr);
+ Assert.assertEquals(acnrManr, i - aFrom);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static boolean isEqual(ArrayType<?> at, Object a, int aFromIndex, int aToIndex,
+ Object b, int bFromIndex, int bToIndex) {
+ int aLength = aToIndex - aFromIndex;
+ int bLength = bToIndex - bFromIndex;
+ if (aLength != bLength)
+ return false;
+
+ for (int i = 0; i < aLength; i++) {
+ Object av = at.get(a, aFromIndex++);
+ Object bv = at.get(b, bFromIndex++);
+ if (!Objects.equals(av, bv)) return false;
+ }
+
+ return true;
+ }
+
+ static boolean isEqual(ArrayType<?> at, Object a, int aFrom, Object b, int bFrom) {
+ Object av = at.get(a, aFrom);
+ Object bv = at.get(b, bFrom);
+
+ return Objects.equals(av, bv);
+ }
+
+ static int[] ranges(int from, int to) {
+ int width = to - from;
+ switch (width) {
+ case 0:
+ return new int[]{};
+ case 1:
+ return new int[]{from, to};
+ case 2:
+ return new int[]{from, from + 1, to};
+ case 3:
+ return new int[]{from, from + 1, from + 2, to};
+ default:
+ return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to)
+ .filter(i -> i >= from && i <= to)
+ .distinct().toArray();
+ }
+ }
+
+
+ // Null array reference tests
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testNullArrayRefs(ArrayType<?> arrayType) {
+ Object n = null;
+ Object a = arrayType.construct(0);
+
+ Assert.assertTrue(arrayType.equals(n, n));
+ Assert.assertFalse(arrayType.equals(n, a));
+ Assert.assertFalse(arrayType.equals(a, n));
+
+ Assert.assertEquals(arrayType.compare(n, n), 0);
+ Assert.assertTrue(arrayType.compare(n, a) < 0);
+ Assert.assertTrue(arrayType.compare(a, n) > 0);
+ }
+
+
+ // Exception throwing tests
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testNPEs(ArrayType<?> arrayType) {
+ Object[] values = new Object[]{null, arrayType.construct(0)};
+
+ for (Object o1 : values) {
+ for (Object o2 : values) {
+ if (o1 != null && o2 != null)
+ continue;
+
+ testNPE(() -> arrayType.equals(o1, 0, 0, o2, 0, 0));
+ testNPE(() -> arrayType.compare(o1, 0, 0, o2, 0, 0));
+ testNPE(() -> arrayType.mismatch(o1, o2));
+ testNPE(() -> arrayType.mismatch(o1, 0, 0, o2, 0, 0));
+ }
+ }
+ }
+
+ @Test
+ public void testObjectNPEs() {
+ String[][] values = new String[][]{null, new String[0]};
+ Comparator<String> c = String::compareTo;
+ Comparator[] cs = new Comparator[]{null, c};
+
+ for (String[] o1 : values) {
+ for (String[] o2 : values) {
+ for (Comparator o3 : cs) {
+ if (o1 != null && o2 != null && o3 != null)
+ continue;
+
+ if (o3 == null) {
+ testNPE(() -> Arrays.compare(o1, o2, o3));
+ testNPE(() -> Arrays.mismatch(o1, o2, o3));
+ }
+
+ testNPE(() -> Arrays.compare(o1, 0, 0, o2, 0, 0, o3));
+ testNPE(() -> Arrays.mismatch(o1, 0, 0, o2, 0, 0, o3));
+ }
+ }
+ }
+ }
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testIAEs(ArrayType<?> arrayType) {
+ List<Integer> values = Arrays.asList(0, 1);
+
+ for (int s : values) {
+ Object a = arrayType.construct(s);
+
+ for (int o1 : values) {
+ for (int o2 : values) {
+ if (o1 <= o2) continue;
+
+ testIAE(() -> arrayType.equals(a, o1, 0, a, o2, 0));
+ testIAE(() -> arrayType.compare(a, o1, 0, a, o2, 0));
+ testIAE(() -> arrayType.mismatch(a, o1, 0, a, o2, 0));
+ }
+ }
+ }
+ }
+
+ @Test(dataProvider = "arrayTypesProvider")
+ public void testAIOBEs(ArrayType<?> arrayType) {
+ List<Integer> froms = Arrays.asList(-1, 0);
+
+ for (int s : Arrays.asList(0, 1)) {
+ List<Integer> tos = Arrays.asList(s, s + 1);
+ Object a = arrayType.construct(s);
+
+ for (int aFrom : froms) {
+ for (int aTo : tos) {
+ for (int bFrom : froms) {
+ for (int bTo : tos) {
+ if (aFrom >= 0 && aTo <= s &&
+ bFrom >= 0 && bTo <= s) continue;
+
+ testAIOBE(() -> arrayType.equals(a, aFrom, aTo, a, bFrom, bTo));
+ testAIOBE(() -> arrayType.compare(a, aFrom, aTo, a, bFrom, bTo));
+ testAIOBE(() -> arrayType.mismatch(a, aFrom, aTo, a, bFrom, bTo));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static void testNPE(Runnable r) {
+ testThrowable(r, NullPointerException.class);
+ }
+
+ static void testIAE(Runnable r) {
+ testThrowable(r, IllegalArgumentException.class);
+ }
+
+ static void testAIOBE(Runnable r) {
+ testThrowable(r, ArrayIndexOutOfBoundsException.class);
+ }
+
+ static void testThrowable(Runnable r, Class<? extends Throwable> expected) {
+ Throwable caught = null;
+ try {
+ r.run();
+ }
+ catch (Throwable t) {
+ caught = t;
+ }
+ Assert.assertNotNull(caught);
+ Assert.assertTrue(expected.isInstance(caught));
+ }
+}
\ No newline at end of file