Array Util: seach, insert, append, remove, copy, shuffle
/*
* @(#)$Id: ArrayUtils.java 3619 2008-03-26 07:23:03Z yui $
*
* Copyright 2006-2008 Makoto YUI
*
* Licensed 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.
*
* Contributors:
* Makoto YUI - ported from jakarta commons lang
*/
/*
* Copyright 2002-2004 The Apache Software Foundation
*
* Licensed 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 xbird.util.lang;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Random;
/**
*
* <DIV lang="en"></DIV>
* <DIV lang="ja"></DIV>
*
* @author Makoto YUI (yuin405+xbird@gmail.com)
*/
public final class ArrayUtils {
/**
* The index value when an element is not found in a list or array: <code>-1</code>.
* This value is returned by methods in this class and can also be used in comparisons with values returned by
* various method from {@link java.util.List}.
*/
public static final int INDEX_NOT_FOUND = -1;
private ArrayUtils() {}
public static <T> T[] copy(final T[] original) {
return copyOf(original, original.length);
}
public static int[] copy(final int[] original) {
return copyOf(original, original.length);
}
/**
* <p>Returns the length of the specified array.
* This method can deal with <code>Object</code> arrays and with primitive arrays.</p>
*
* <p>If the input array is <code>null</code>, <code>0</code> is returned.</p>
*
* <pre>
* ArrayUtils.getLength(null) = 0
* ArrayUtils.getLength([]) = 0
* ArrayUtils.getLength([null]) = 1
* ArrayUtils.getLength([true, false]) = 2
* ArrayUtils.getLength([1, 2, 3]) = 3
* ArrayUtils.getLength(["a", "b", "c"]) = 3
* </pre>
*
* @param array the array to retrieve the length from, may be null
* @return The length of the array, or <code>0</code> if the array is <code>null</code>
* @throws IllegalArgumentException if the object arguement is not an array.
*/
public static int getLength(final Object array) {
if(array == null) {
return 0;
} else {
return Array.getLength(array);
}
}
public static <T> int indexOf(final T[] array, final T value) {
final int alen = array.length;
for(int i = 0; i < alen; i++) {
if(value.equals(array[i])) {
return i;
}
}
return INDEX_NOT_FOUND;
}
public static <T> int indexOf(final T[] array, final T value, final int startIndex) {
final int alen = array.length;
for(int i = startIndex; i < alen; i++) {
if(value.equals(array[i])) {
return i;
}
}
return INDEX_NOT_FOUND;
}
public static int indexOf(final int[] array, final int value) {
final int alen = array.length;
for(int i = 0; i < alen; i++) {
if(value == array[i]) {
return i;
}
}
return INDEX_NOT_FOUND;
}
public static int indexOf(final int[] array, final int valueToFind, int startIndex, int endIndex) {
if(array == null) {
return INDEX_NOT_FOUND;
}
final int til = Math.min(endIndex, array.length);
if(startIndex < 0 || startIndex > til) {
throw new IllegalArgumentException("Illegal startIndex: " + startIndex);
}
for(int i = startIndex; i < til; i++) {
if(valueToFind == array[i]) {
return i;
}
}
return INDEX_NOT_FOUND;
}
public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
if(array == null) {
return INDEX_NOT_FOUND;
}
if(startIndex < 0) {
startIndex = 0;
}
for(int i = startIndex; i < array.length; i++) {
if(valueToFind == array[i]) {
return i;
}
}
return INDEX_NOT_FOUND;
}
/**
* Returns the last index of the given array or -1 if empty or null.
* This method can deal with <code>Object</code> arrays and with primitive arrays.
* This value is one less than the size since arrays indices are 0-based.</p>
*
* <pre>
* ArrayUtils.lastIndex(null) = -1
* ArrayUtils.lastIndex([]) = -1
* ArrayUtils.lastIndex([null]) = 0
* ArrayUtils.lastIndex([true, false]) = 1
* ArrayUtils.lastIndex([1, 2, 3]) = 2
* ArrayUtils.lastIndex(["a", "b", "c"]) = 2
* </pre>
*
* @param array the array to return the last index for, may be null
* @return the last index, -1 if empty or null
* @throws IllegalArgumentException if the object arguement is not an array.
*/
public static int lastIndex(final Object array) {
return ArrayUtils.getLength(array) - 1;
}
/**
* <p>Inserts the specified element at the specified position in the array.
* Shifts the element currently at that position (if any) and any subsequent
* elements to the right (adds one to their indices).</p>
*
* <p>This method returns a new array with the same elements of the input
* array plus the given element on the specified position. The component
* type of the returned array is always the same as that of the input
* array.</p>
*
* <p>If the input array is <code>null</code>, a new one element array is returned
* whose component type is the same as the element.</p>
*
* <pre>
* ArrayUtils.insert(null, 0, null) = [null]
* ArrayUtils.insert(null, 0, "a") = ["a"]
* ArrayUtils.insert(["a"], 1, null) = ["a", null]
* ArrayUtils.insert(["a"], 1, "b") = ["a", "b"]
* ArrayUtils.insert(["a", "b"], 3, "c") = ["a", "b", "c"]
* </pre>
*
* @param array the array to add the element to, may be <code>null</code>
* @param index the position of the new object
* @param element the object to add
* @return A new array containing the existing elements and the new element
* @throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index > array.length).
*/
@SuppressWarnings("unchecked")
public static <T> T[] insert(final Object array, final int index, final Object element) {
if(array == null) {
if(index != 0) {
throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
}
Object joinedArray = Array.newInstance(element != null ? element.getClass()
: Object.class, 1);
Array.set(joinedArray, 0, element);
return (T[]) joinedArray;
}
int length = getLength(array);
if(index > length || index < 0) {
throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
}
Object result = Array.newInstance(array.getClass().getComponentType(), length + 1);
System.arraycopy(array, 0, result, 0, index);
Array.set(result, index, element);
if(index < length) {
System.arraycopy(array, index, result, index + 1, length - index);
}
return (T[]) result;
}
public static long[] insert(final long[] array, final long element) {
long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
newArray[lastIndex(newArray)] = element;
return newArray;
}
public static long[] insert(final long[] vals, final int idx, final long val) {
long[] newVals = new long[vals.length + 1];
if(idx > 0) {
System.arraycopy(vals, 0, newVals, 0, idx);
}
newVals[idx] = val;
if(idx < vals.length) {
System.arraycopy(vals, idx, newVals, idx + 1, vals.length - idx);
}
return newVals;
}
public static byte[][] insert(final byte[][] vals, final int idx, final byte[] val) {
byte[][] newVals = new byte[vals.length + 1][];
if(idx > 0) {
System.arraycopy(vals, 0, newVals, 0, idx);
}
newVals[idx] = val;
if(idx < vals.length) {
System.arraycopy(vals, idx, newVals, idx + 1, vals.length - idx);
}
return newVals;
}
public static byte[] append(final byte[] b1, final byte[] b2) {
final byte[] nb = new byte[b1.length + b2.length];
if(b1.length > 0) {
System.arraycopy(b1, 0, nb, 0, b1.length);
}
if(b2.length > 0) {
System.arraycopy(b2, 0, nb, b1.length, b2.length);
}
return nb;
}
public static int[] append(final int[] left, final int[] right) {
final int[] n = new int[left.length + right.length];
if(left.length > 0) {
System.arraycopy(left, 0, n, 0, left.length);
}
if(right.length > 0) {
System.arraycopy(right, 0, n, left.length, right.length);
}
return n;
}
/**
* <p>Removes the element at the specified position from the specified array.
* All subsequent elements are shifted to the left (substracts one from
* their indices).</p>
*
* <p>This method returns a new array with the same elements of the input
* array except the element on the specified position. The component
* type of the returned array is always the same as that of the input
* array.</p>
*
* <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
* will be thrown, because in that case no valid index can be specified.</p>
*
* @param array the array to remove the element from, may not be <code>null</code>
* @param index the position of the element to be removed
* @return A new array containing the existing elements except the element
* at the specified position.
* @throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= array.length), or if the array is <code>null</code>.
* @since 2.1
*/
@SuppressWarnings("unchecked")
public static <T> T[] remove(final T[] array, final int index) {
int length = getLength(array);
if(index < 0 || index >= length) {
throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
}
Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
System.arraycopy(array, 0, result, 0, index);
if(index < length - 1) {
System.arraycopy(array, index + 1, result, index, length - index - 1);
}
return (T[]) result;
}
@SuppressWarnings("unchecked")
public static <T> T[] remove(final T[] array, final int from, final int to) {
assert (to >= from) : to + " - " + from;
int length = getLength(array);
if(from < 0 || to >= length) {
throw new IndexOutOfBoundsException("from: " + from + ", to: " + to + ", Length: "
+ length);
}
int remsize = to - from + 1;
Object result = Array.newInstance(array.getClass().getComponentType(), length - remsize);
System.arraycopy(array, 0, result, 0, from);
if(to < length - 1) {
System.arraycopy(array, to + 1, result, from, length - to - 1);
}
return (T[]) result;
}
public static long[] remove(final long[] vals, final int idx) {
long[] newVals = new long[vals.length - 1];
if(idx > 0) {
System.arraycopy(vals, 0, newVals, 0, idx);
}
if(idx < newVals.length) {
System.arraycopy(vals, idx + 1, newVals, idx, newVals.length - idx);
}
return newVals;
}
public static long[] remove(final long[] vals, final int from, final int to) {
int remsize = to - from + 1;
long[] newVals = new long[vals.length - remsize];
if(from > 0) {
System.arraycopy(vals, 0, newVals, 0, from);
}
if(to < newVals.length) {
System.arraycopy(vals, to + 1, newVals, from, newVals.length - to);
}
return newVals;
}
/**
* Returns a copy of the given array of size 1 greater than the argument.
* The last value of the array is left to the default value.
*
* @param array The array to copy, must not be <code>null</code>.
* @param newArrayComponentType If <code>array</code> is <code>null</code>, create a
* size 1 array of this type.
* @return A new copy of the array of size 1 greater than the input.
*/
private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
if(array != null) {
int arrayLength = Array.getLength(array);
Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
System.arraycopy(array, 0, newArray, 0, arrayLength);
return newArray;
} else {
return Array.newInstance(newArrayComponentType, 1);
}
}
public static boolean equals(final char[] a, final char[] a2, final int off, final int len) {
if(a == a2) {
return true;
}
if(a == null || a2 == null) {
return false;
}
int length = a.length;
if(len != length) {
return false;
}
for(int i = 0; i < len; i++) {
if(a[i] != a2[off + i]) {
return false;
}
}
return true;
}
public static char[] copyOfRange(final char[] original, final int from, final int to) {
final int newLength = to - from;
if(newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
final char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
public static byte[] copyOfRange(final byte[] original, final int from, final int to) {
final int newLength = to - from;
if(newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
final byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
public static int[] copyOfRange(final int[] original, final int from, final int to) {
final int newLength = to - from;
if(newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
final int[] copy = new int[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
public static long[] copyOfRange(final long[] original, final int from, final int to) {
final int newLength = to - from;
if(newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
final long[] copy = new long[newLength];
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
@SuppressWarnings("unchecked")
public static <T> T[] copyOfRange(final T[] original, final int from, final int to) {
return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
}
@SuppressWarnings("unchecked")
private static <T, U> T[] copyOfRange(final U[] original, final int from, final int to, final Class<? extends T[]> newType) {
final int newLength = to - from;
if(newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
final T[] copy = ((Object) newType == (Object) Object[].class) ? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
return copy;
}
public static byte[] copyOf(final byte[] original, final int newLength) {
final byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
public static int[] copyOf(final int[] original, final int newLength) {
final int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
public static char[] copyOf(final char[] original, final int newLength) {
final char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
@SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
@SuppressWarnings("unchecked")
public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
final T[] copy = ((Object) newType == (Object) Object[].class) ? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
@SuppressWarnings("unchecked")
public static int binarySearch(final Object[] a, final int fromIndex, final int toIndex, final Object key) {
int low = fromIndex;
int high = toIndex - 1;
while(low <= high) {
int mid = (low + high) >>> 1;
Comparable midVal = (Comparable) a[mid];
int cmp = midVal.compareTo(key);
if(cmp < 0) {
low = mid + 1;
} else if(cmp > 0) {
high = mid - 1;
} else {
return mid; // key found
}
}
return -(low + 1); // key not found.
}
/**
* Reverses the order of the given array.
*/
public static void reverse(final int[] ary) {
if(ary == null) {
return;
}
int i = 0;
int j = ary.length - 1;
int tmp;
while(j > i) {
tmp = ary[j];
ary[j] = ary[i];
ary[i] = tmp;
j--;
i++;
}
}
public static int[] reverseTo(final int[] ary) {
if(ary == null) {
return null;
}
int[] b = new int[ary.length];
for(int i = 0; i < ary.length; i++) {
b[ary.length - i - 1] = ary[i];
}
return b;
}
public static Object resize(final Object[] ary, final int length) {
final Object newary = Array.newInstance(ary.getClass().getComponentType(), length);
final int copysize = length > ary.length ? length : ary.length;
System.arraycopy(ary, 0, newary, 0, copysize);
return newary;
}
public static byte[] resize(final byte[] ary, final int length) {
final byte[] newary = new byte[length];
final int copysize = length > ary.length ? ary.length : length;
System.arraycopy(ary, 0, newary, 0, copysize);
return newary;
}
public static boolean startsWith(final byte[] target, final byte[] prefix) {
final int testlen = prefix.length;
if(target.length < testlen) {
return false;
}
for(int i = 0; i < testlen; i++) {
if(target[i] != prefix[i]) {
return false;
}
}
return true;
}
public static int compareTo(final byte lhs[], final byte rhs[]) {
if(lhs == rhs) {
return 0;
}
final int len = Math.min(lhs.length, rhs.length);
for(int i = 0; i < len; i++) {
if(lhs[i] != rhs[i]) {
return (lhs[i] & 0xFF) - (rhs[i] & 0xFF);
}
}
return lhs.length - rhs.length;
}
public static int compareTo(final byte lhs[], final byte rhs[], final int offset) {
final int len = Math.min(lhs.length, rhs.length);
for(int i = offset; i < len; i++) {
if(lhs[i] != rhs[i]) {
return (lhs[i] & 0xFF) - (rhs[i] & 0xFF);
}
}
return lhs.length - rhs.length;
}
public static int compareTo(final byte lhs[], final byte rhs[], final int offset, final int length) {
int tolen = offset + length;
final int limit = Math.min(Math.min(lhs.length, rhs.length), tolen);
for(int i = offset; i < limit; i++) {
if(lhs[i] != rhs[i]) {
return (lhs[i] & 0xFF) - (rhs[i] & 0xFF);
}
}
return 0;
}
public static int compareTo(final byte[] b1, final int off1, final int len1, final byte[] b2, final int off2, final int len2) {
for(int i = 0; i < len1 && i < len2; i++) {
final int d = (b1[off1 + i] & 0xFF) - (b2[off2 + i] & 0xFF);
if(d != 0) {
return d;
}
}
return len1 - len2;
}
public static int compareTo(final int lhs[], final int rhs[]) {
if(lhs == rhs) {
return 0;
}
final int len = Math.min(lhs.length, rhs.length);
for(int i = 0; i < len; i++) {
if(lhs[i] != rhs[i]) {
return lhs[i] - rhs[i];
}
}
return lhs.length - rhs.length;
}
public static <T> boolean contains(final T[] array, final T value) {
final int len = array.length;
for(int i = 0; i < len; i++) {
if(array[i].equals(value)) {
return true;
}
}
return false;
}
public static int longestCommonPrefix(final byte[] ary, final byte[] root) {
final int limit = Math.min(ary.length, root.length);
for(int i = 0; i < limit; i++) {
if(ary[i] != root[i]) {
return i;
}
}
return limit;
}
public static void shuffle(final Object[] array) {
final Random r = new Random();
final int limit = array.length;
for(int i = 0; i < limit; ++i) {
swap(array, i, r.nextInt(limit));
}
}
public static void shuffle(final int[] array) {
final Random r = new Random();
final int limit = array.length;
for(int i = 0; i < limit; ++i) {
swap(array, i, r.nextInt(limit));
}
}
public static void shuffle(final Object[] array, final long seed) {
final Random r = new Random(seed);
final int limit = array.length;
for(int i = 0; i < limit; ++i) {
swap(array, i, r.nextInt(limit));
}
}
public static void swap(final Object[] array, final int i, final int j) {
Object o = array[i];
array[i] = array[j];
array[j] = o;
}
public static void swap(final int[] array, final int i, final int j) {
int o = array[i];
array[i] = array[j];
array[j] = o;
}
public static double max(final double[] array) {
double d = Double.MIN_VALUE;
for(int i = 0; i < array.length; i++) {
d = Math.max(array[i], d);
}
return d;
}
public static <T> T max(final T[] array, final double[] scores) {
if(array.length != scores.length) {
throw new IllegalArgumentException("array.length(" + array.length
+ ") != scores.length(" + scores.length + ")");
}
T obj = null;
double d = Double.MIN_VALUE;
for(int i = 0; i < scores.length; i++) {
final double score = scores[i];
if(score > d) {
d = score;
obj = array[i];
}
}
return obj;
}
public static int minIndex(final float[] scores) {
int index = -1;
float min = Float.MAX_VALUE;
for(int i = 0; i < scores.length; i++) {
final float f = scores[i];
if(f < min) {
min = f;
index = i;
}
}
return index;
}
@SuppressWarnings("unchecked")
public static <T> Class<T[]> getArrayClass(Class<T> clazz) {
Object array = Array.newInstance(clazz, 0);
return (Class<T[]>) array.getClass();
}
@SuppressWarnings("unchecked")
public static <T> T[] toArray(final Collection<T> c, final Class<? extends T[]> newType) {
final int length = c.size();
final T[] array = (T[]) Array.newInstance(newType.getComponentType(), length);
if(length > 0) {
int i = 0;
for(final T elem : c) {
array[i++] = elem;
}
}
return array;
}
}
Related examples in the same category