java.util.Arrays Maven / Gradle / Ivy
Show all versions of jtransc-rt Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util;
import com.jtransc.annotation.JTranscMethodBody;
import com.jtransc.mem.FastMemByte;
import java.io.Serializable;
import java.lang.reflect.Array;
/**
* {@code Arrays} contains static methods which operate on arrays.
*
* @since 1.2
*/
public class Arrays {
private static class ArrayList extends AbstractList implements
List, Serializable, RandomAccess {
private final E[] a;
ArrayList(E[] storage) {
if (storage == null) {
throw new NullPointerException("storage == null");
}
a = storage;
}
@Override
public boolean contains(Object object) {
if (object != null) {
for (E element : a) {
if (object.equals(element)) {
return true;
}
}
} else {
for (E element : a) {
if (element == null) {
return true;
}
}
}
return false;
}
@Override
public E get(int location) {
try {
return a[location];
} catch (ArrayIndexOutOfBoundsException e) {
//throw java.util.ArrayList.throwIndexOutOfBoundsException(location, a.length);
throw new IndexOutOfBoundsException();
}
}
@Override
public int indexOf(Object object) {
if (object != null) {
for (int i = 0; i < a.length; i++) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = 0; i < a.length; i++) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
@Override
public int lastIndexOf(Object object) {
if (object != null) {
for (int i = a.length - 1; i >= 0; i--) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = a.length - 1; i >= 0; i--) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
@Override
public E set(int location, E object) {
E result = a[location];
a[location] = object;
return result;
}
@Override
public int size() {
return a.length;
}
@Override
public Object[] toArray() {
return a.clone();
}
@Override
@SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"})
public T[] toArray(T[] contents) {
int size = size();
if (size > contents.length) {
Class> ct = contents.getClass().getComponentType();
contents = (T[]) Array.newInstance(ct, size);
}
System.arraycopy(a, 0, contents, 0, size);
if (size < contents.length) {
contents[size] = null;
}
return contents;
}
}
private Arrays() {
/* empty */
}
/**
* Returns a {@code List} of the objects in the specified array. The size of the
* {@code List} cannot be modified, i.e. adding and removing are unsupported, but
* the elements can be set. Setting an element modifies the underlying
* array.
*
* @param array
* the array.
* @return a {@code List} of the elements of the specified array.
*/
@SafeVarargs
public static List asList(T... array) {
return new ArrayList(array);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(byte[] array, byte value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(byte[] array, int startIndex, int endIndex, byte value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
byte midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(char[] array, char value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(char[] array, int startIndex, int endIndex, char value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
char midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(double[] array, double value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(double[] array, int startIndex, int endIndex, double value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
double midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else if (midVal != 0 && midVal == value) {
return mid; // value found
} else { // Either midVal and value are == 0 or at least one is NaN
long midValBits = Double.doubleToLongBits(midVal);
long valueBits = Double.doubleToLongBits(value);
if (midValBits < valueBits) {
lo = mid + 1; // (-0.0, 0.0) or (not NaN, NaN); midVal < val
} else if (midValBits > valueBits) {
hi = mid - 1; // (0.0, -0.0) or (NaN, not NaN); midVal > val
} else {
return mid; // bit patterns are equal; value found
}
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(float[] array, float value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(float[] array, int startIndex, int endIndex, float value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
float midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else if (midVal != 0 && midVal == value) {
return mid; // value found
} else { // Either midVal and value are == 0 or at least one is NaN
int midValBits = Float.floatToIntBits(midVal);
int valueBits = Float.floatToIntBits(value);
if (midValBits < valueBits) {
lo = mid + 1; // (-0.0, 0.0) or (not NaN, NaN); midVal < val
} else if (midValBits > valueBits) {
hi = mid - 1; // (0.0, -0.0) or (NaN, not NaN); midVal > val
} else {
return mid; // bit patterns are equal; value found
}
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(int[] array, int value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(int[] array, int startIndex, int endIndex, int value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
int midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(long[] array, long value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(long[] array, int startIndex, int endIndex, long value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
long midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws ClassCastException
* if an element in the array or the search element does not
* implement {@code Comparable}, or cannot be compared to each other.
*/
public static int binarySearch(Object[] array, Object value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws ClassCastException
* if an element in the array or the search element does not
* implement {@code Comparable}, or cannot be compared to each other.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(Object[] array, int startIndex, int endIndex, Object value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
@SuppressWarnings("unchecked")
int midValCmp = ((Comparable) array[mid]).compareTo(value);
if (midValCmp < 0) {
lo = mid + 1;
} else if (midValCmp > 0) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* using {@code comparator} to compare elements.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @param comparator the {@code Comparator} used to compare the elements.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws ClassCastException
* if an element in the array or the search element does not
* implement {@code Comparable}, or cannot be compared to each other.
*/
public static int binarySearch(T[] array, T value, Comparator super T> comparator) {
return binarySearch(array, 0, array.length, value, comparator);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive),
* using {@code comparator} to compare elements.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @param comparator the {@code Comparator} used to compare the elements.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws ClassCastException
* if an element in the array or the search element does not
* implement {@code Comparable}, or cannot be compared to each other.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(T[] array, int startIndex, int endIndex, T value,
Comparator super T> comparator) {
if (comparator == null) {
return binarySearch(array, startIndex, endIndex, value);
}
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
int midValCmp = comparator.compare(array[mid], value);
if (midValCmp < 0) {
lo = mid + 1;
} else if (midValCmp > 0) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array}.
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
*/
public static int binarySearch(short[] array, short value) {
return binarySearch(array, 0, array.length, value);
}
/**
* Performs a binary search for {@code value} in the ascending sorted array {@code array},
* in the range specified by fromIndex (inclusive) and toIndex (exclusive).
* Searching in an unsorted array has an undefined result. It's also undefined which element
* is found if there are multiple occurrences of the same element.
*
* @param array the sorted array to search.
* @param startIndex the inclusive start index.
* @param endIndex the exclusive start index.
* @param value the element to find.
* @return the non-negative index of the element, or a negative index which
* is {@code -index - 1} where the element would be inserted.
* @throws IllegalArgumentException if {@code startIndex > endIndex}
* @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
* @since 1.6
*/
public static int binarySearch(short[] array, int startIndex, int endIndex, short value) {
checkBinarySearchBounds(startIndex, endIndex, array.length);
int lo = startIndex;
int hi = endIndex - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
short midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
private static void checkBinarySearchBounds(int startIndex, int endIndex, int length) {
if (startIndex > endIndex) {
throw new IllegalArgumentException();
}
if (startIndex < 0 || endIndex > length) {
throw new ArrayIndexOutOfBoundsException();
}
}
public static void fill(byte[] array, byte value) {
fill(array, 0, array.length, value);
}
public static void fill(short[] array, short value) {
fill(array, 0, array.length, value);
}
public static void fill(char[] array, char value) {
fill(array, 0, array.length, value);
}
public static void fill(int[] array, int value) {
fill(array, 0, array.length, value);
}
public static void fill(long[] array, long value) {
fill(array, 0, array.length, value);
}
public static void fill(float[] array, float value) {
fill(array, 0, array.length, value);
}
public static void fill(double[] array, double value) {
fill(array, 0, array.length, value);
}
public static void fill(boolean[] array, boolean value) {
fill(array, 0, array.length, value);
}
public static void fill(Object[] array, Object value) {
fill(array, 0, array.length, value);
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_B, p0)->fill(p1, p2, p3);")
public static void fill(byte[] array, int start, int end, byte value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_S, p0)->fill(p1, p2, p3);")
public static void fill(short[] array, int start, int end, short value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_C, p0)->fill(p1, p2, p3);")
public static void fill(char[] array, int start, int end, char value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_I, p0)->fill(p1, p2, p3);")
public static void fill(int[] array, int start, int end, int value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_J, p0)->fill(p1, p2, p3);")
public static void fill(long[] array, int start, int end, long value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_F, p0)->fill(p1, p2, p3);")
public static void fill(float[] array, int start, int end, float value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_D, p0)->fill(p1, p2, p3);")
public static void fill(double[] array, int start, int end, double value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_Z, p0)->fill(p1, p2, p3);")
public static void fill(boolean[] array, int start, int end, boolean value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
@JTranscMethodBody(target = "cpp", value = "GET_OBJECT(JA_L, p0)->fill(p1, p2, p3);")
public static void fill(Object[] array, int start, int end, Object value) {
Arrays.checkStartAndEnd(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code boolean} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Boolean} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(boolean[] array) {
if (array == null) return 0;
int hashCode = 1;
for (boolean element : array) {
// 1231, 1237 are hash code values for boolean value
hashCode = 31 * hashCode + (element ? 1231 : 1237);
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* not-null {@code int} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Integer} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(int[] array) {
if (array == null) return 0;
int hashCode = 1;
for (int element : array) {
// the hash code value for integer value is integer value itself
hashCode = 31 * hashCode + element;
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code short} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Short} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(short[] array) {
if (array == null) return 0;
int hashCode = 1;
for (short element : array) {
// the hash code value for short value is its integer value
hashCode = 31 * hashCode + element;
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code char} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Character} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(char[] array) {
if (array == null) return 0;
int hashCode = 1;
for (char element : array) {
// the hash code value for char value is its integer value
hashCode = 31 * hashCode + element;
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code byte} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Byte} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(byte[] array) {
if (array == null) return 0;
int hashCode = 1;
for (byte element : array) {
// the hash code value for byte value is its integer value
hashCode = 31 * hashCode + element;
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code long} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Long} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(long[] array) {
if (array == null) return 0;
int hashCode = 1;
for (long elementValue : array) {
/*
* the hash code value for long value is (int) (value ^ (value >>>
* 32))
*/
hashCode = 31 * hashCode + (int) (elementValue ^ (elementValue >>> 32));
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code float} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Float} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(float[] array) {
if (array == null) return 0;
int hashCode = 1;
for (float element : array) {
/*
* the hash code value for float value is
* Float.floatToIntBits(value)
*/
hashCode = 31 * hashCode + Float.floatToIntBits(element);
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. For any two
* {@code double} arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the
* {@link List#hashCode()} method which is invoked on a {@link List}
* containing a sequence of {@link Double} instances representing the
* elements of array in the same order. If the array is {@code null}, the return
* value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(double[] array) {
if (array == null) return 0;
int hashCode = 1;
for (double element : array) {
long v = Double.doubleToLongBits(element);
/*
* the hash code value for double value is (int) (v ^ (v >>> 32))
* where v = Double.doubleToLongBits(value)
*/
hashCode = 31 * hashCode + (int) (v ^ (v >>> 32));
}
return hashCode;
}
/**
* Returns a hash code based on the contents of the given array. If the
* array contains other arrays as its elements, the hash code is based on
* their identities not their contents. So it is acceptable to invoke this
* method on an array that contains itself as an element, either directly or
* indirectly.
*
* For any two arrays {@code a} and {@code b}, if
* {@code Arrays.equals(a, b)} returns {@code true}, it means
* that the return value of {@code Arrays.hashCode(a)} equals
* {@code Arrays.hashCode(b)}.
*
* The value returned by this method is the same value as the method
* Arrays.asList(array).hashCode(). If the array is {@code null}, the return value
* is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int hashCode(Object[] array) {
if (array == null) return 0;
int hashCode = 1;
for (Object element : array) {
hashCode = 31 * hashCode + ((element == null) ? 0 : (element).hashCode());
}
return hashCode;
}
/**
* Returns a hash code based on the "deep contents" of the given array. If
* the array contains other arrays as its elements, the hash code is based
* on their contents not their identities. So it is not acceptable to invoke
* this method on an array that contains itself as an element, either
* directly or indirectly.
*
* For any two arrays {@code a} and {@code b}, if
* {@code Arrays.deepEquals(a, b)} returns {@code true}, it
* means that the return value of {@code Arrays.deepHashCode(a)} equals
* {@code Arrays.deepHashCode(b)}.
*
* The computation of the value returned by this method is similar to that
* of the value returned by {@link List#hashCode()} invoked on a
* {@link List} containing a sequence of instances representing the
* elements of array in the same order. The difference is: If an element e
* of array is itself an array, its hash code is computed by calling the
* appropriate overloading of {@code Arrays.hashCode(e)} if e is an array of a
* primitive type, or by calling {@code Arrays.deepHashCode(e)} recursively if e is
* an array of a reference type. The value returned by this method is the
* same value as the method {@code Arrays.asList(array).hashCode()}. If the array is
* {@code null}, the return value is 0.
*
* @param array
* the array whose hash code to compute.
* @return the hash code for {@code array}.
*/
public static int deepHashCode(Object[] array) {
if (array == null) return 0;
int hashCode = 1;
for (Object element : array) {
int elementHashCode = deepHashCodeElement(element);
hashCode = 31 * hashCode + elementHashCode;
}
return hashCode;
}
private static int deepHashCodeElement(Object element) {
Class> cl;
if (element == null) return 0;
cl = element.getClass().getComponentType();
if (cl == null) return element.hashCode();
if (!cl.isPrimitive()) return deepHashCode((Object[]) element);
if (cl.equals(int.class)) return hashCode((int[]) element);
if (cl.equals(char.class)) return hashCode((char[]) element);
if (cl.equals(boolean.class)) return hashCode((boolean[]) element);
if (cl.equals(byte.class)) return hashCode((byte[]) element);
if (cl.equals(long.class)) return hashCode((long[]) element);
if (cl.equals(float.class)) return hashCode((float[]) element);
if (cl.equals(double.class)) return hashCode((double[]) element);
return hashCode((short[]) element);
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code byte} array.
* @param array2
* the second {@code byte} array.
* @return {@code true} if both arrays are {@code null} or if the arrays have the
* same length and the elements at each index in the two arrays are
* equal, {@code false} otherwise.
*/
public static boolean equals(byte[] array1, byte[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) return false;
}
return true;
}
public static boolean equals(short[] array1, short[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) return false;
}
return true;
}
public static boolean equals(char[] array1, char[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) return false;
}
return true;
}
public static boolean equals(int[] array1, int[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) return false;
}
return true;
}
public static boolean equals(long[] array1, long[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) return false;
}
return true;
}
public static boolean equals(float[] array1, float[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (Float.floatToIntBits(array1[i]) != Float.floatToIntBits(array2[i])) return false;
}
return true;
}
public static boolean equals(double[] array1, double[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (Double.doubleToLongBits(array1[i]) != Double.doubleToLongBits(array2[i])) return false;
}
return true;
}
public static boolean equals(boolean[] array1, boolean[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) return false;
}
return true;
}
public static boolean equals(Object[] array1, Object[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
Object e1 = array1[i], e2 = array2[i];
if (!(e1 == null ? e2 == null : e1.equals(e2))) return false;
}
return true;
}
public static boolean deepEquals(Object[] array1, Object[] array2) {
if (array1 == array2) return true;
if (array1 == null || array2 == null || array1.length != array2.length) return false;
for (int i = 0; i < array1.length; i++) {
Object e1 = array1[i], e2 = array2[i];
if (!deepEqualsElements(e1, e2)) return false;
}
return true;
}
private static boolean deepEqualsElements(Object e1, Object e2) {
Class> cl1, cl2;
if (e1 == e2) {
return true;
}
if (e1 == null || e2 == null) {
return false;
}
cl1 = e1.getClass().getComponentType();
cl2 = e2.getClass().getComponentType();
if (cl1 != cl2) {
return false;
}
if (cl1 == null) {
return e1.equals(e2);
}
/*
* compare as arrays
*/
if (!cl1.isPrimitive()) {
return deepEquals((Object[]) e1, (Object[]) e2);
}
if (cl1.equals(int.class)) {
return equals((int[]) e1, (int[]) e2);
}
if (cl1.equals(char.class)) {
return equals((char[]) e1, (char[]) e2);
}
if (cl1.equals(boolean.class)) {
return equals((boolean[]) e1, (boolean[]) e2);
}
if (cl1.equals(byte.class)) {
return equals((byte[]) e1, (byte[]) e2);
}
if (cl1.equals(long.class)) {
return equals((long[]) e1, (long[]) e2);
}
if (cl1.equals(float.class)) {
return equals((float[]) e1, (float[]) e2);
}
if (cl1.equals(double.class)) {
return equals((double[]) e1, (double[]) e2);
}
return equals((short[]) e1, (short[]) e2);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code byte} array to be sorted.
*/
public static void sort(byte[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order.
*
* @param array
* the {@code byte} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static void sort(byte[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
/**
* Checks that the range described by {@code offset} and {@code count} doesn't exceed
* {@code arrayLength}.
*
* @hide
*/
public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
throw new ArrayIndexOutOfBoundsException();
}
}
/**
* Checks that the range described by {@code start} and {@code end} doesn't exceed
* {@code len}.
*
* @hide
*/
public static void checkStartAndEnd(int len, int start, int end) {
if (start < 0 || end > len)
throw new ArrayIndexOutOfBoundsException("start < 0 || end > len. start=" + start + ", end=" + end + ", len=" + len);
if (start > end) throw new IllegalArgumentException("start > end: " + start + " > " + end);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code char} array to be sorted.
*/
public static void sort(char[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order.
*
* @param array
* the {@code char} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static void sort(char[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code double} array to be sorted.
* @see #sort(double[], int, int)
*/
public static void sort(double[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order. The
* values are sorted according to the order imposed by {@code Double.compareTo()}.
*
* @param array
* the {@code double} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
* @see Double#compareTo(Double)
*/
public static void sort(double[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code float} array to be sorted.
* @see #sort(float[], int, int)
*/
public static void sort(float[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order. The
* values are sorted according to the order imposed by {@code Float.compareTo()}.
*
* @param array
* the {@code float} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
* @see Float#compareTo(Float)
*/
public static void sort(float[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code int} array to be sorted.
*/
public static void sort(int[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order.
*
* @param array
* the {@code int} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static void sort(int[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code long} array to be sorted.
*/
public static void sort(long[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order.
*
* @param array
* the {@code long} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static void sort(long[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
/**
* Sorts the specified array in ascending numerical order.
*
* @param array
* the {@code short} array to be sorted.
*/
public static void sort(short[] array) {
DualPivotQuicksort.sort(array);
}
/**
* Sorts the specified range in the array in ascending numerical order.
*
* @param array
* the {@code short} array to be sorted.
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static void sort(short[] array, int start, int end) {
DualPivotQuicksort.sort(array, start, end);
}
// BEGIN android-note
/*
*
If this platform has an optimizing VM, check whether ComparableTimSort
* offers any performance benefit over TimSort in conjunction with a
* comparator that returns:
* {@code ((Comparable)first).compareTo(Second)}.
* If not, you are better off deleting ComparableTimSort to eliminate the
* code duplication. In other words, the commented out code below
* is the preferable implementation for sorting arrays of Comparables if it
* offers sufficient performance.
*/
// /**
// * A comparator that implements the natural order of a group of
// * mutually comparable elements. Using this comparator saves us
// * from duplicating most of the code in this file (one version for
// * Comparables, one for explicit comparators).
// */
// private static final Comparator