如何正确组合谓词过滤器?

Kra*_*0da 2 java java-stream

我想创建将 Predicate::and 合并到一个谓词中的方法,并将其提交到输入列表中。我有代码:

public static List<?> getFilteredList(Collection<?> collection, Collection<Predicate<?>> filters) {
    return collection.stream()
            .filter(filters.stream().reduce(Predicate::and).orElse(t -> true))
            .collect(Collectors.toList());

}
Run Code Online (Sandbox Code Playgroud)

但是编译器说有一个错误 Predicate::and Incompatible types: Predicate<capture of ?> is not convertible to Predicate<? super capture of ?>

如何解决?

And*_*ner 5

就目前而言,您可能会提供完全不兼容的谓词:

Collection<Predicate<?>> predicates = 
    List.of((String s) -> s.isEmpty(), (Integer i) -> i >= 0)
Run Code Online (Sandbox Code Playgroud)

把这些结合起来是没有意义的。

您需要提供与collection元素兼容的谓词:

public static <T> List<T> getFilteredList(
    Collection<? extends T> collection,
    Collection<? extends Predicate<? super T>> predicates) {

  Predicate<T> combined = predicates.stream().reduce(t -> true, Predicate::and, Predicate::and);
  return collection.stream()
      .filter(combined)
      .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

我在这里的通配符上有点进城。你可以用更简单的方式来做,代价是它接受的参数的灵活性:

public static <T> List<T> getFilteredList(
    Collection<T> collection,
    Collection<Predicate<T>> predicates) {

  Predicate<T> combined = predicates.stream().reduce(t -> true, Predicate::and);
  return collection.stream()
      .filter(combined)
      .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)