/*
* 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 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<E> extends AbstractList<E> implements
List<E>, Serializable, RandomAccess {
private static final long serialVersionUID = -2764017481108945198L;
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);
}
}
@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> 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 <T> List<T> asList(T... array) {
return new ArrayList<T>(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 <T> 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 <T> 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();
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code byte} array to fill.
* @param value
* the {@code byte} element.
*/
public static void fill(byte[] array, byte value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code byte} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code byte} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code short} array to fill.
* @param value
* the {@code short} element.
*/
public static void fill(short[] array, short value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code short} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code short} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code char} array to fill.
* @param value
* the {@code char} element.
*/
public static void fill(char[] array, char value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code char} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code char} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code int} array to fill.
* @param value
* the {@code int} element.
*/
public static void fill(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code int} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code int} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code long} array to fill.
* @param value
* the {@code long} element.
*/
public static void fill(long[] array, long value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code long} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code long} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code float} array to fill.
* @param value
* the {@code float} element.
*/
public static void fill(float[] array, float value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code float} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code float} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code double} array to fill.
* @param value
* the {@code double} element.
*/
public static void fill(double[] array, double value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code double} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code double} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code boolean} array to fill.
* @param value
* the {@code boolean} element.
*/
public static void fill(boolean[] array, boolean value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code boolean} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code boolean} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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;
}
}
/**
* Fills the specified array with the specified element.
*
* @param array
* the {@code Object} array to fill.
* @param value
* the {@code Object} element.
*/
public static void fill(Object[] array, Object value) {
for (int i = 0; i < array.length; i++) {
array[i] = value;
}
}
/**
* Fills the specified range in the array with the specified element.
*
* @param array
* the {@code Object} array to fill.
* @param start
* the first index to fill.
* @param end
* the last + 1 index to fill.
* @param value
* the {@code Object} element.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
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)}.
* <p>
* 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)}.
* <p>
* 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)}.
* <p>
* 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)}.
* <p>
* 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)}.
* <p>
* 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)}.
* <p>
* 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)}.
* <p>
* 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)}.
* <p>
* 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.
* <p>
* 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)}.
* <p>
* 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) {
int elementHashCode;
if (element == null) {
elementHashCode = 0;
} else {
elementHashCode = (element).hashCode();
}
hashCode = 31 * hashCode + elementHashCode;
}
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.
* <p>
* 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)}.
* <p>
* 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();
}
/*
* element is an array
*/
if (element instanceof Object[]) {
return deepHashCode((Object[]) element);
} else if (cl == int.class) {
return hashCode((int[]) element);
} else if (cl == char.class) {
return hashCode((char[]) element);
} else if (cl == boolean.class) {
return hashCode((boolean[]) element);
} else if (cl == byte.class) {
return hashCode((byte[]) element);
} else if (cl == long.class) {
return hashCode((long[]) element);
} else if (cl == float.class) {
return hashCode((float[]) element);
} else if (cl == double.class) {
return hashCode((double[]) element);
} else {
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;
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code short} array.
* @param array2
* the second {@code short} 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(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;
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code char} array.
* @param array2
* the second {@code char} 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(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;
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code int} array.
* @param array2
* the second {@code int} 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(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;
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code long} array.
* @param array2
* the second {@code long} 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(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;
}
/**
* Compares the two arrays. The values are compared in the same manner as
* {@code Float.equals()}.
*
* @param array1
* the first {@code float} array.
* @param array2
* the second {@code float} 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.
* @see Float#equals(Object)
*/
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;
}
/**
* Compares the two arrays. The values are compared in the same manner as
* {@code Double.equals()}.
*
* @param array1
* the first {@code double} array.
* @param array2
* the second {@code double} 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.
* @see Double#equals(Object)
*/
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;
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code boolean} array.
* @param array2
* the second {@code boolean} 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(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;
}
/**
* Compares the two arrays.
*
* @param array1
* the first {@code Object} array.
* @param array2
* the second {@code Object} 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 according to {@code equals()}, {@code false} otherwise.
*/
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;
}
/**
* Returns {@code true} if the two given arrays are deeply equal to one another.
* Unlike the method {@code equals(Object[] array1, Object[] array2)}, this method
* is appropriate for use for nested arrays of arbitrary depth.
* <p>
* Two array references are considered deeply equal if they are both {@code null},
* or if they refer to arrays that have the same length and the elements at
* each index in the two arrays are equal.
* <p>
* Two {@code null} elements {@code element1} and {@code element2} are possibly deeply equal if any
* of the following conditions satisfied:
* <p>
* {@code element1} and {@code element2} are both arrays of object reference types, and
* {@code Arrays.deepEquals(element1, element2)} would return {@code true}.
* <p>
* {@code element1} and {@code element2} are arrays of the same primitive type, and the
* appropriate overloading of {@code Arrays.equals(element1, element2)} would return
* {@code true}.
* <p>
* {@code element1 == element2}
* <p>
* {@code element1.equals(element2)} would return {@code true}.
* <p>
* Note that this definition permits {@code null} elements at any depth.
* <p>
* If either of the given arrays contain themselves as elements, the
* behavior of this method is uncertain.
*
* @param array1
* the first {@code Object} array.
* @param array2
* the second {@code Object} 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 according to {@code equals()}, {@code false} otherwise.
*/
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 (e1 instanceof Object[]) {
return deepEquals((Object[]) e1, (Object[]) e2);
} else if (cl1 == int.class) {
return equals((int[]) e1, (int[]) e2);
} else if (cl1 == char.class) {
return equals((char[]) e1, (char[]) e2);
} else if (cl1 == boolean.class) {
return equals((boolean[]) e1, (boolean[]) e2);
} else if (cl1 == byte.class) {
return equals((byte[]) e1, (byte[]) e2);
} else if (cl1 == long.class) {
return equals((long[]) e1, (long[]) e2);
} else if (cl1 == float.class) {
return equals((float[]) e1, (float[]) e2);
} else if (cl1 == double.class) {
return equals((double[]) e1, (double[]) e2);
} else {
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(arrayLength, offset,
count);
}
}
/**
* 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
/*
* <p>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<Object> NATURAL_ORDER = new Comparator<Object>() {
// @SuppressWarnings("unchecked")
// public int compare(Object first, Object second) {
// return ((Comparable<Object>)first).compareTo(second);
// }
// };
//
// public static void sort(Object[] a) {
// sort(a, 0, a.length, NATURAL_ORDER);
// }
//
// public static void sort(Object[] a, int fromIndex, int toIndex) {
// sort(a, fromIndex, toIndex, NATURAL_ORDER);
// }
// END android-note
/**
* Sorts the specified array in ascending natural order.
*
* @throws ClassCastException if any element does not implement {@code Comparable},
* or if {@code compareTo} throws for any pair of elements.
*/
public static void sort(Object[] array) {
ComparableTimSort.sort(array);
}
/**
* Sorts the specified range in the array in ascending natural order.
*
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @throws ClassCastException if any element does not implement {@code Comparable},
* or if {@code compareTo} throws for any pair of elements.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static void sort(Object[] array, int start, int end) {
ComparableTimSort.sort(array, start, end);
}
/**
* Sorts the specified range in the array using the specified {@code Comparator}.
* All elements must be comparable to each other without a
* {@code ClassCastException} being thrown.
*
* @param start
* the start index to sort.
* @param end
* the last + 1 index to sort.
* @param comparator
* the {@code Comparator}.
* @throws ClassCastException
* if elements in the array cannot be compared to each other
* using the given {@code Comparator}.
* @throws IllegalArgumentException
* if {@code start > end}.
* @throws ArrayIndexOutOfBoundsException
* if {@code start < 0} or {@code end > array.length}.
*/
public static <T> void sort(T[] array, int start, int end, Comparator<? super T> comparator) {
TimSort.sort(array, start, end, comparator);
}
/**
* Sorts the specified array using the specified {@code Comparator}. All elements
* must be comparable to each other without a {@code ClassCastException} being thrown.
*
* @throws ClassCastException
* if elements in the array cannot be compared to each other
* using the {@code Comparator}.
*/
public static <T> void sort(T[] array, Comparator<? super T> comparator) {
TimSort.sort(array, comparator);
}
/**
* Creates a {@code String} representation of the {@code boolean[]} passed.
* The result is surrounded by brackets ({@code "[]"}), each
* element is converted to a {@code String} via the
* {@link String#valueOf(boolean)} and separated by {@code ", "}.
* If the array is {@code null}, then {@code "null"} is returned.
*
* @param array
* the {@code boolean} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(boolean[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 7);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code byte[]} passed. The
* result is surrounded by brackets ({@code "[]"}), each element
* is converted to a {@code String} via the {@link String#valueOf(int)} and
* separated by {@code ", "}. If the array is {@code null}, then
* {@code "null"} is returned.
*
* @param array
* the {@code byte} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(byte[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 6);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code char[]} passed. The
* result is surrounded by brackets ({@code "[]"}), each element
* is converted to a {@code String} via the {@link String#valueOf(char)} and
* separated by {@code ", "}. If the array is {@code null}, then
* {@code "null"} is returned.
*
* @param array
* the {@code char} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(char[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 3);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code double[]} passed.
* The result is surrounded by brackets ({@code "[]"}), each
* element is converted to a {@code String} via the
* {@link String#valueOf(double)} and separated by {@code ", "}.
* If the array is {@code null}, then {@code "null"} is returned.
*
* @param array
* the {@code double} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(double[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 7);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code float[]} passed.
* The result is surrounded by brackets ({@code "[]"}), each
* element is converted to a {@code String} via the
* {@link String#valueOf(float)} and separated by {@code ", "}.
* If the array is {@code null}, then {@code "null"} is returned.
*
* @param array
* the {@code float} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(float[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 7);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code int[]} passed. The
* result is surrounded by brackets ({@code "[]"}), each element
* is converted to a {@code String} via the {@link String#valueOf(int)} and
* separated by {@code ", "}. If the array is {@code null}, then
* {@code "null"} is returned.
*
* @param array
* the {@code int} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(int[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 6);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code long[]} passed. The
* result is surrounded by brackets ({@code "[]"}), each element
* is converted to a {@code String} via the {@link String#valueOf(long)} and
* separated by {@code ", "}. If the array is {@code null}, then
* {@code "null"} is returned.
*
* @param array
* the {@code long} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(long[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 6);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code short[]} passed.
* The result is surrounded by brackets ({@code "[]"}), each
* element is converted to a {@code String} via the
* {@link String#valueOf(int)} and separated by {@code ", "}. If
* the array is {@code null}, then {@code "null"} is returned.
*
* @param array
* the {@code short} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(short[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 6);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a {@code String} representation of the {@code Object[]} passed.
* The result is surrounded by brackets ({@code "[]"}), each
* element is converted to a {@code String} via the
* {@link String#valueOf(Object)} and separated by {@code ", "}.
* If the array is {@code null}, then {@code "null"} is returned.
*
* @param array
* the {@code Object} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String toString(Object[] array) {
if (array == null) {
return "null";
}
if (array.length == 0) {
return "[]";
}
StringBuilder sb = new StringBuilder(array.length * 7);
sb.append('[');
sb.append(array[0]);
for (int i = 1; i < array.length; i++) {
sb.append(", ");
sb.append(array[i]);
}
sb.append(']');
return sb.toString();
}
/**
* Creates a <i>"deep"</i> {@code String} representation of the
* {@code Object[]} passed, such that if the array contains other arrays,
* the {@code String} representation of those arrays is generated as well.
* <p>
* If any of the elements are primitive arrays, the generation is delegated
* to the other {@code toString} methods in this class. If any element
* contains a reference to the original array, then it will be represented
* as {@code "[...]"}. If an element is an {@code Object[]}, then its
* representation is generated by a recursive call to this method. All other
* elements are converted via the {@link String#valueOf(Object)} method.
*
* @param array
* the {@code Object} array to convert.
* @return the {@code String} representation of {@code array}.
* @since 1.5
*/
public static String deepToString(Object[] array) {
// Special case null to prevent NPE
if (array == null) {
return "null";
}
// delegate this to the recursive method
StringBuilder buf = new StringBuilder(array.length * 9);
deepToStringImpl(array, new Object[] { array }, buf);
return buf.toString();
}
/**
* Implementation method used by {@link #deepToString(Object[])}.
*
* @param array
* the {@code Object[]} to dive into.
* @param origArrays
* the original {@code Object[]}; used to test for self
* references.
* @param sb
* the {@code StringBuilder} instance to append to or
* {@code null} one hasn't been created yet.
* @return the result.
* @see #deepToString(Object[])
*/
private static void deepToStringImpl(Object[] array, Object[] origArrays,
StringBuilder sb) {
if (array == null) {
sb.append("null");
return;
}
sb.append('[');
for (int i = 0; i < array.length; i++) {
if (i != 0) {
sb.append(", ");
}
// establish current element
Object elem = array[i];
if (elem == null) {
// element is null
sb.append("null");
} else {
// get the Class of the current element
Class<?> elemClass = elem.getClass();
if (elemClass.isArray()) {
// element is an array type
// get the declared Class of the array (element)
Class<?> elemElemClass = elemClass.getComponentType();
if (elemElemClass.isPrimitive()) {
// element is a primitive array
if (boolean.class.equals(elemElemClass)) {
sb.append(toString((boolean[]) elem));
} else if (byte.class.equals(elemElemClass)) {
sb.append(toString((byte[]) elem));
} else if (char.class.equals(elemElemClass)) {
sb.append(toString((char[]) elem));
} else if (double.class.equals(elemElemClass)) {
sb.append(toString((double[]) elem));
} else if (float.class.equals(elemElemClass)) {
sb.append(toString((float[]) elem));
} else if (int.class.equals(elemElemClass)) {
sb.append(toString((int[]) elem));
} else if (long.class.equals(elemElemClass)) {
sb.append(toString((long[]) elem));
} else if (short.class.equals(elemElemClass)) {
sb.append(toString((short[]) elem));
} else {
// no other possible primitives, so we assert that
throw new AssertionError();
}
} else {
// element is an Object[], so we assert that
// assert elem instanceof Object[];
if (deepToStringImplContains(origArrays, elem)) {
sb.append("[...]");
} else {
Object[] newArray = (Object[]) elem;
Object[] newOrigArrays = new Object[origArrays.length + 1];
System.arraycopy(origArrays, 0, newOrigArrays, 0,
origArrays.length);
newOrigArrays[origArrays.length] = newArray;
// make the recursive call to this method
deepToStringImpl(newArray, newOrigArrays, sb);
}
}
} else { // element is NOT an array, just an Object
sb.append(array[i]);
}
}
}
sb.append(']');
}
/**
* Utility method used to assist the implementation of
* {@link #deepToString(Object[])}.
*
* @param origArrays
* An array of Object[] references.
* @param array
* An Object[] reference to look for in {@code origArrays}.
* @return A value of {@code true} if {@code array} is an
* element in {@code origArrays}.
*/
private static boolean deepToStringImplContains(Object[] origArrays,
Object array) {
if (origArrays == null || origArrays.length == 0) {
return false;
}
for (Object element : origArrays) {
if (element == array) {
return true;
}
}
return false;
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code false}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static boolean[] copyOf(boolean[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code (byte) 0}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static byte[] copyOf(byte[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code '\\u0000'}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static char[] copyOf(char[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code 0.0d}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static double[] copyOf(double[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code 0.0f}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static float[] copyOf(float[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code 0}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static int[] copyOf(int[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code 0L}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static long[] copyOf(long[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code (short) 0}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static short[] copyOf(short[] original, int newLength) {
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code null}.
*
* @param original the original array
* @param newLength the length of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static <T> T[] copyOf(T[] original, int newLength) {
if (original == null) {
throw new NullPointerException("original == null");
}
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength);
}
/**
* Copies {@code newLength} elements from {@code original} into a new array.
* If {@code newLength} is greater than {@code original.length}, the result is padded
* with the value {@code null}.
*
* @param original the original array
* @param newLength the length of the new array
* @param newType the class of the new array
* @return the new array
* @throws NegativeArraySizeException if {@code newLength < 0}
* @throws NullPointerException if {@code original == null}
* @throws ArrayStoreException if a value in {@code original} is incompatible with T
* @since 1.6
*/
public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
// We use the null pointer check in copyOfRange for exception priority compatibility.
if (newLength < 0) {
throw new NegativeArraySizeException(Integer.toString(newLength));
}
return copyOfRange(original, 0, newLength, newType);
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code false}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static boolean[] copyOfRange(boolean[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
boolean[] result = new boolean[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code (byte) 0}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static byte[] copyOfRange(byte[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
byte[] result = new byte[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code '\\u0000'}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static char[] copyOfRange(char[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
char[] result = new char[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code 0.0d}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static double[] copyOfRange(double[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
double[] result = new double[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code 0.0f}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static float[] copyOfRange(float[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
float[] result = new float[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code 0}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static int[] copyOfRange(int[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
int[] result = new int[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code 0L}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static long[] copyOfRange(long[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
long[] result = new long[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code (short) 0}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
public static short[] copyOfRange(short[] original, int start, int end) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
short[] result = new short[resultLength];
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code null}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @since 1.6
*/
@SuppressWarnings("unchecked")
public static <T> T[] copyOfRange(T[] original, int start, int end) {
int originalLength = original.length; // For exception priority compatibility.
if (start > end) {
throw new IllegalArgumentException();
}
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), resultLength);
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
/**
* Copies elements from {@code original} into a new array, from indexes start (inclusive) to
* end (exclusive). The original order of elements is preserved.
* If {@code end} is greater than {@code original.length}, the result is padded
* with the value {@code null}.
*
* @param original the original array
* @param start the start index, inclusive
* @param end the end index, exclusive
* @return the new array
* @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
* @throws IllegalArgumentException if {@code start > end}
* @throws NullPointerException if {@code original == null}
* @throws ArrayStoreException if a value in {@code original} is incompatible with T
* @since 1.6
*/
@SuppressWarnings("unchecked")
public static <T, U> T[] copyOfRange(U[] original, int start, int end, Class<? extends T[]> newType) {
if (start > end) {
throw new IllegalArgumentException();
}
int originalLength = original.length;
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
T[] result = (T[]) Array.newInstance(newType.getComponentType(), resultLength);
System.arraycopy(original, start, result, 0, copyLength);
return result;
}
}