在java中,无法直接通过 T[] array = new T[size]创建泛型数组,否则在编译阶段就会提示报错,但是我们可以利用Array.newInstance()方法来实现泛型数组类及其工具类。
泛型数组类:
import java.lang.reflect.Array;
/**
* Desc.
*
* @author chenxj(陈贤靖)
* @date 2018/12/8
*/
public class GenericArray<T> {
private T[] mArray;
private Class<T> mClazz;
@SuppressWarnings("unchecked")
public GenericArray(Class<T> clazz, int size) {
mArray = (T[]) Array.newInstance(clazz, size);
mClazz = clazz;
}
public T get(int index) {
return mArray != null ? mArray[index] : null;
}
public void set(T element, int index) {
if (mArray != null) {
mArray[index] = element;
}
}
@SuppressWarnings("unchecked")
public void add(T element) {
if (mArray == null) {
throw new IllegalStateException("please init mArray first");
}
if (element == null) {
throw new IllegalArgumentException("illegal argument");
}
T[] arrayNew = (T[]) Array.newInstance(mClazz, mArray.length + 1);
for (int i = 0; i < arrayNew.length; i++) {
arrayNew[i] = i == (arrayNew.length - 1) ? element : mArray[i];
}
this.mArray = arrayNew;
}
/**
* T 类如果不是原始数据类型,则需要重写equals方法,否则会失效
* @param target
*/
@SuppressWarnings("unchecked")
public void remove(T target) {
if (mArray == null) {
throw new IllegalStateException("please init mArray first");
}
if (target == null) {
throw new IllegalArgumentException("illegal argument");
}
T[] arrayNew = (T[]) Array.newInstance(mClazz, mArray.length - 1);
for (int i = 0; i < arrayNew.length; i++) {
for (T element : mArray) {
if (!element.equals(target)) {
arrayNew[i] = element;
break;
}
}
}
}
/**
* 删除闭区间范围内的数组元素
*
* @param beginIndex
* @param endIndex
* @return
*/
@SuppressWarnings("unchecked")
public void removeElements(int beginIndex, int endIndex) {
if (mArray == null) {
throw new IllegalStateException("please init mArray first");
}
if (beginIndex > endIndex || endIndex >= mArray.length || beginIndex < 0) {
throw new IllegalArgumentException("illegal arguments");
}
T[] arrayNew = (T[]) Array.newInstance(mClazz, mArray.length - (endIndex - beginIndex + 1));
for (int i = 0; i < arrayNew.length; i++) {
for (int j = i; j < mArray.length; j++) {
if (j < beginIndex || j > endIndex) {
arrayNew[i] = mArray[j];
break;
}
}
}
}
public T[] getArray() {
return mArray;
}
}
工具类:
import java.lang.reflect.Array;
/**
* 数组工具类
*
* @author chenxj(陈贤靖)
* @date 2018/12/7
*/
public class ArrayUtils {
/**
* 删除目标元素,需考虑类 T 是否重写equals()方法
* @param original
* @param clazz
* @param target
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T[] removeElement(T[] original, Class<T> clazz, T target) {
if (original == null || target == null) {
throw new IllegalArgumentException("illegal arguments");
}
T[] arrayNew = (T[]) Array.newInstance(clazz, original.length - 1);
for (int i = 0; i < arrayNew.length; i++) {
for (T element : original) {
if (!element.equals(target)) {
arrayNew[i] = element;
break;
}
}
}
return arrayNew;
}
/**
* 删除闭区间范围内的数组元素
*
* @param original
* @param beginIndex
* @param endIndex
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T[] removeElements(T[] original, Class<T> clazz, int beginIndex, int endIndex) {
if (original == null || beginIndex > endIndex || endIndex >= original.length || beginIndex < 0) {
throw new IllegalArgumentException("illegal arguments");
}
T[] arrayNew = (T[]) Array.newInstance(clazz, original.length - (endIndex - beginIndex + 1));
for (int i = 0; i < arrayNew.length; i++) {
for (int j = i; j < original.length; j++) {
if (j < beginIndex || j > endIndex) {
arrayNew[i] = original[j];
break;
}
}
}
return arrayNew;
}
}
其中,removeElement()方法需要注意传入参数对应的类如果是基本数据类型,可以直接使用,如果是已重写equals方法的复杂数据类型,如String、Date、Integer等,也可以直接使用,否则,需要重写equals方法,才能生效。
查看Array.newInstance()方法,可知该方法会重新分配一个指定类型和大小的数组:
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}
private static Object newArray(Class<?> componentType, int size) throws NegativeArraySizeException {
if (!componentType.isPrimitive()) {
return createObjectArray(componentType, size);
} else if (componentType == char.class) {
return new char[size];
} else if (componentType == int.class) {
return new int[size];
} else if (componentType == byte.class) {
return new byte[size];
} else if (componentType == boolean.class) {
return new boolean[size];
} else if (componentType == short.class) {
return new short[size];
} else if (componentType == long.class) {
return new long[size];
} else if (componentType == float.class) {
return new float[size];
} else if (componentType == double.class) {
return new double[size];
} else if (componentType == void.class) {
throw new IllegalArgumentException("Can't allocate an array of void");
}
throw new AssertionError();
}