0

考虑以下代码:

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;
    }
};

为什么我不能使用第二个谓词 with filter()

4

2 回答 2

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;
}

这就是说,只要谓词函数愿意接受不小于 type 的类型T使用 type 的实例T(或进一步派生自 的某种类型T)调用它就可以正常工作。

于 2011-07-10T00:26:05.640 回答
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;
}

这就是CollectionsJava Collections 库中的类在其实用方法中为泛型提供支持所做的工作。在 1.5 之前Collections.EMPTY_LIST,在添加泛型之后会返回一个List<Object>. 但是,这不会返回一个适当的泛型列表,因此Collections.emptyList()被添加以返回List适合调用上下文的任何类型。

于 2011-07-10T00:20:56.627 回答