请考虑以下代码:
ICondition searchCondition, scopeCondition...
List<ICondition> filtered = CollectionUtil.filter(
Arrays.asList(searchCondition, scopeCondition),
CollectionUtil.isNonNull);
无法编译:
“
filter(Collection<T>, CollectionUtil.Predicate<T>)
类型中的方法CollectionUtil
不适用于参数(List<ICondition>, CollectionUtil.Predicate<Object>)
”
如果我定义一个ICondition
特定的isNonNull()
谓词,那么一切都很好,但这是愚蠢的,我不明白什么是错的或如何解决它。
以下是我的实用功能:
public interface Predicate<T>
{
boolean apply(T type);
}
public static <T> List<T> filter(Collection<T> target, Predicate<T> predicate)
{
target = Collections.unmodifiableCollection(target);
List<T> result = new ArrayList<T>();
for (T element: target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
// This predicate works as expected.
public static CollectionUtil.Predicate<String> isStringNonBlank = new CollectionUtil.Predicate<String>() {
public boolean apply (String item) {
return !StringUtils.isBlank(item);
}
};
// This predicate looks fine, but fails in usage.
public static CollectionUtil.Predicate<Object> isNonNull = new CollectionUtil.Predicate<Object>() {
public boolean apply (Object item) {
return null != item;
}
};
为什么我不能将第二个谓词与filter()
一起使用?
答案 0 :(得分:7)
您的filter
函数的predicate
参数似乎不是逆变。尝试按如下方式重写:
public static <T> List<T> filter(Collection<? extends T> source,
Predicate<? super T> predicate)
{
final List<T> result = new ArrayList<T>(source.size());
for (T element: source)
if (predicate.apply(element))
result.add(element);
return result;
}
这就是说,只要谓词函数愿意接受类型 narrower 而不是类型T
,就用类型为T
的实例调用它(或者一些进一步派生自T
)的类型将正常工作。
答案 1 :(得分:2)
尝试验证isNonNull
:
private static class IsNonNullPredicate<T> implements Predicate<T> {
public boolean apply(T item) {
return null != item;
}
}
现在,您可以通过util类中的泛型方法而不是常量返回它。
public <T> Predicate<T> isNonNull() {
return new IsNonNullPredicate<T>();
}
或者,只需对存储的实例执行未经检查的强制转换,而不是每次都创建一个新的:
private final Predicate isNotNullPredicate = new IsNonNullPredicate();
public <T> Predicate<T> isNonNull() {
return (Predicate<T>) isNotNullPredicate;
}
这就是Java Collections库中的Collections
类在其实用程序方法中为泛型提供支持的功能。在1.5之前,Collections.EMPTY_LIST
在添加泛型后会返回List<Object>
。但是,这不会返回适当的通用列表,因此添加Collections.emptyList()
以返回适合调用上下文的任何类型的List
。