package util;
import java.lang.reflect.Array;
public class ArrayUtils
{
/*****************************************************************************
* Syntactic sugar: "new T[] {...}" -> "arr(...)".
*
* When passed 0 elements, T will default to Object.
*/
@SafeVarargs public static <T> T[] arr(T... ts)
{
return ts;
}
/* For nested literal arrays, up to 8 levels of nesting.
* e.g. arr3(arr2(arr(x, y), arr(z)), arr2(arr(u)) */
@SafeVarargs public static <T> T[][] arr2(T[]... ts)
{ return ts; }
@SafeVarargs public static <T> T[][][] arr3(T[][]... ts)
{ return ts; }
@SafeVarargs public static <T> T[][][][] arr4(T[][][]... ts)
{ return ts; }
@SafeVarargs public static <T> T[][][][][] arr5(T[][][][]... ts)
{ return ts; }
@SafeVarargs public static <T> T[][][][][][] arr6(T[][][][][]... ts)
{ return ts; }
@SafeVarargs public static <T> T[][][][][][][] arr7(T[][][][][][]... ts)
{ return ts; }
@SafeVarargs public static <T> T[][][][][][][][] arr8(T[][][][][][][]... ts)
{ return ts; }
/* Those single-argument versions are needed because Java is dumb at detecting
* types: arr2(new String[0]) would otherwise result in T = Object, return
* type = Object[][]. Java actually believes that the string array is an array
* that substitutes for all variadic parameters, instead of a single variadic
* parameter itself. */
public static <T> T[][] arr2(T[] t)
{ return (T[][]) single(t); }
public static <T> T[][][] arr3(T[][] t)
{ return (T[][][]) single(t); }
public static <T> T[][][][] arr4(T[][][] t)
{ return (T[][][][]) single(t); }
public static <T> T[][][][][] arr5(T[][][][] t)
{ return (T[][][][][]) single(t); }
public static <T> T[][][][][][] arr6(T[][][][][] t)
{ return (T[][][][][][]) single(t); }
public static <T> T[][][][][][][] arr7(T[][][][][][] t)
{ return (T[][][][][][][]) single(t); }
public static <T> T[][][][][][][][] arr8(T[][][][][][][] t)
{ return (T[][][][][][][][]) single(t); }
/*****************************************************************************
* Creates a new array whose single element is elem. This is only type-safe
* when T is an array type (no sub-typing possible).
*/
private static <T> T[] single(T elem)
{
@SuppressWarnings("unchecked")
T[] out = (T[]) Array.newInstance(elem.getClass(), 1);
out[0] = elem;
return out;
}
/*****************************************************************************
* Returns a new empty array whose element type is the type of witness.
* It's generally cleaner to use "new T[0]" instead.
*
* This is type-safe because the array is empty.
*/
public static <T> T[] arr0(T witness)
{
@SuppressWarnings("unchecked")
T[] out = (T[]) Array.newInstance(witness.getClass(), 0);
return out;
}
/*****************************************************************************
* Returns the concatenation of one array and one item.
*/
public static <T> T[] concat(T[] one, T two)
{
@SuppressWarnings("unchecked") T[] out =
(T[]) Array.newInstance(two.getClass(), one.length + 1);
System.arraycopy(one, 0, out, 0, one.length);
out[one.length] = two;
return out;
}
/*****************************************************************************
* Returns the concatenation of two arrays.
*/
public static <T> T[] concat(T[] one, T[] two)
{
@SuppressWarnings("unchecked") T[] out = (T[]) Array.newInstance(
one.getClass().getComponentType(), one.length + two.length);
System.arraycopy(one, 0, out, 0, one.length);
System.arraycopy(two, 0, out, one.length, two.length);
return out;
}
/*****************************************************************************
* Returns a cartesian product. "one" contains sequences of T. The returned
* arrays contains a copy of each sequence in "one" for each element in two:
* that copy had the element of two appended.
*/
public static <T> T[][] cartesian(T[][] one, T[] two)
{
@SuppressWarnings("unchecked") T[][] out =
(T[][]) Array.newInstance(two.getClass(), one.length * two.length);
for (int i = 0; i < one.length; ++i) {
for (int j = 0; j < two.length; ++j) {
out[i * two.length + j] = ArrayUtils.concat(one[i], two[j]);
}
}
return out;
}
/*****************************************************************************
* Returns true iff "element" is contained within "array".
*/
public static <T> boolean contains(T[] array, T element)
{
return search(array, element) != -1;
}
/*****************************************************************************
* Returns the first index at which "element" appears within array, of -1 if
* it does not appear.
*/
public static <T> int search(T[] array, T element)
{
for (int i = 0 ; i < array.length ; ++i) {
if (array[i].equals(element)) {
return i;
}
}
return -1;
}
/*****************************************************************************
* Returns true iff the supplied elements are contained, in the same order
* (but not necessarily adjacent) within "array".
*/
public static <T> boolean contains(T[] array, T[] elements)
{
if (elements.length == 0) {
return true;
}
int i = 0;
for (T e : array) {
if (e.equals(elements[i]) && ++i == elements.length) {
return true;
}
}
return false;
}
}