我正在编写一种方法,该方法使用“谓词”过滤特定的Collection并返回仅包含已过滤元素(Predicate返回true的元素)的新Collection。

像这样的东西:

    public <T> Collection<T> filter(Collection<T> collection, Closure<T> predicate);


我知道,在Java中,由于类型擦除,我不能只在运行时创建新的Collection()

我还通过向该方法传递一个额外的参数来调用T.newInstance()来了解“变通方法”。

这看起来像:

    public <T> Collection<T> filter(Class<? extends Collection<T>> collectionToInstanciate, Collection<T> collection, Closure<T> predicate) {

        // create the new Collection
        Collection<T> container = collectionToInstanciate.newInstance();

        // and then add only filtered items
        Iterator<T> iter = collection.iterator();
        while (iter.hasNext()) {
            T obj = iter.next();

            // if Predicate.invoke() returns true, then keep element, otherwise skip it
            if (predicate.invoke(obj)) {
                container.add(obj);
            }
        }
        return container;
    }


但是我应该怎么称呼我的方法呢?

例如,如果我只需要一个整数列表的奇数,我想这样做:

    // instanciate ArrayList<Integer> = [1, 2, 3, 4, 5]
    ArrayList<Integer> array = ...;

    // return a new LinkedList<Integer> with only odd numbers
    filter(LinkedList<Integer>.class, array, new Closure<Integer>() {
        public Boolean invoke(Integer arg_p) {
            return (arg_p % 2 == 0);
        }
    });

    // should return [2, 4] as a LinkedList<Integer>


问题是

    LinkedList<Integer>.class


不编译。

我应该如何声明以正确实例化filter()方法中的LinkedList?

问候,

最佳答案

泛型是编译时的功能,在运行时没有任何意义。如果您想创建一个LinkedList,那就是您要做的。您无法使编译器根据您在运行时所做的事情给您一个错误。

一个更简单的解决方案是传递您要填充的类的实例。

List<Integer> result = filter(new LinkedList<Integer>(), array,
    new Predicate<Integer>() {
        public boolean invoke(Integer arg_p) {
            return (arg_p % 2 == 0);
        }
    });


它略短一些,可以在编译时检查。

注意:这些谓词中的许多谓词作为普通循环都更加简单快捷。

List<Integer> result = new LinkedList<Integer>();
for(Integer i: array)
    if (i % 2 == 0)
        result.add(i);

关于java - 如何在运行时创建通用Collection <T>?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16927509/

10-14 14:50