ProjectAres/Util/core/src/main/java/tc/oc/commons/core/util/ArrayUtils.java

218 lines
7.1 KiB
Java

package tc.oc.commons.core.util;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import tc.oc.commons.core.reflect.Methods;
public class ArrayUtils {
private ArrayUtils() {}
public static final int NOT_FOUND_INDEX = -1;
public static <T> T fromEnd(T[] array, int index) {
return array[array.length - 1 - index];
}
public static <T> int indexOf(T[] array, T value) {
if(array == null) return NOT_FOUND_INDEX;
if(value == null) {
for(int i = 0; i < array.length; i++) {
if(array[i] == null) return i;
}
} else {
for(int i = 0; i < array.length; i++) {
if(value.equals(array[i])) return i;
}
}
return NOT_FOUND_INDEX;
}
public static <T> boolean contains(T[] array, T value) {
return indexOf(array, value) != NOT_FOUND_INDEX;
}
/**
* Create a new array of given size, with the same component type as the given array
*/
public static <T> T[] sameType(T[] array, int size) {
return (T[]) Array.newInstance(array.getClass().getComponentType(), size);
}
/**
* Similar to {@link Arrays#copyOfRange}, but from can be negative,
* which will copy to an offset in the destination array.
*/
public static <T> T[] copyOfRange(T[] src, int from, int to) {
final T[] dest = sameType(src, to - from);
System.arraycopy(src, Math.max(0, from),
dest, Math.max(0, -from),
Math.min(to, src.length));
return dest;
}
public static <T> T[] append(T[] a, T...b) {
if(b.length == 0) return a;
if(a.length == 0) return b;
T[] result = Arrays.copyOf(a, a.length + b.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
public static <T> T[] prepend(T element, T[] array) {
final T[] result = copyOfRange(array, -1, array.length);
result[0] = element;
return result;
}
public static <T> void copy(Iterable<? extends T> src, T[] dest, int destPos) {
for(T t : src) {
if(destPos >= dest.length) break;
dest[destPos++] = t;
}
}
public static <T> T first(T[] array, Predicate<T> test, T def) {
for(T t : array) {
if(test.test(t)) return t;
}
return def;
}
public static @Nullable <T> T first(T[] array, Predicate<T> test) {
return first(array, test, null);
}
private static final Method APPLY_METHOD = Methods.method(Function.class, "apply", Object.class);
public static <T, U> U[] transform(T[] input, Class<U> outputType, Function<T, U> function) {
return transform(input, (U[]) Array.newInstance(outputType, input.length), function);
}
public static <T, U> U[] transform(T[] input, U[] output, Function<T, U> function) {
for(int i = 0; i < input.length; i++) {
output[i] = function.apply(input[i]);
}
return output;
}
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
public static Object[] zeroObjects() { return EMPTY_OBJECT_ARRAY; }
public static List<Boolean> asList(boolean[] array) {
return new AbstractList<Boolean>() {
@Override public int size() { return array.length; }
@Override public Boolean get(int index) { return array[index]; }
};
}
public static List<Character> asList(char[] array) {
return new AbstractList<Character>() {
@Override public int size() { return array.length; }
@Override public Character get(int index) { return array[index]; }
};
}
public static List<Byte> asList(byte[] array) {
return new AbstractList<Byte>() {
@Override public int size() { return array.length; }
@Override public Byte get(int index) { return array[index]; }
};
}
public static List<Short> asList(short[] array) {
return new AbstractList<Short>() {
@Override public int size() { return array.length; }
@Override public Short get(int index) { return array[index]; }
};
}
public static List<Integer> asList(int[] array) {
return new AbstractList<Integer>() {
@Override public int size() { return array.length; }
@Override public Integer get(int index) { return array[index]; }
};
}
public static List<Long> asList(long[] array) {
return new AbstractList<Long>() {
@Override public int size() { return array.length; }
@Override public Long get(int index) { return array[index]; }
};
}
public static List<Float> asList(float[] array) {
return new AbstractList<Float>() {
@Override public int size() { return array.length; }
@Override public Float get(int index) { return array[index]; }
};
}
public static List<Double> asList(double[] array) {
return new AbstractList<Double>() {
@Override public int size() { return array.length; }
@Override public Double get(int index) { return array[index]; }
};
}
public static List<?> asList(Object array) {
if(!array.getClass().isArray()) {
throw new IllegalArgumentException("Not an array");
}
final Class<?> type = array.getClass().getComponentType();
if(!type.isPrimitive()) {
return Arrays.asList((Object[]) array);
} else if(boolean.class.equals(type)) {
return asList((boolean[]) array);
} else if(char.class.equals(type)) {
return asList((char[]) array);
} else if(byte.class.equals(type)) {
return asList((byte[]) array);
} else if(short.class.equals(type)) {
return asList((short[]) array);
} else if(int.class.equals(type)) {
return asList((int[]) array);
} else if(long.class.equals(type)) {
return asList((long[]) array);
} else if(float.class.equals(type)) {
return asList((float[]) array);
} else if(double.class.equals(type)) {
return asList((double[]) array);
}
throw new IllegalArgumentException("Weird array type: " + type);
}
public static <T> List<T> asSubList(int start, int end, T... array) {
return new AbstractList() {
@Override
public int size() {
return end - start;
}
@Override
public Object get(int index) {
return array[start + index];
}
};
}
public static <T> List<T> asSubListFrom(int start, T... array) {
return asSubList(start, array.length, array);
}
public static <T> List<T> asSubListTo(int end, T... array) {
return asSubList(0, end, array);
}
}