我正在编写一种方法,该方法使用“谓词”过滤特定的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/