Java tutorial
/* * @(#)$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; } }