在Java中创建泛型数组及其工具类

在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();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值