如何将多个谓词应用于java.util.Stream?

我如何应用多个谓词到java.util.Stream的filter()方法?

这是我现在做的,但我不喜欢它。我有一个集合的东西,我需要减少基于过滤器(谓词)集合的事情数量:

Collection<Thing> things = someGenerator.someMethod();
List<Thing> filtered = things.parallelStream().filter(p -> {
   for (Filter f : filtersCollection) {
      if (f.test(p))
        return true;
   }
   return false;
}).collect(Collectors.toList());

我知道,如果我知道前面的过滤器数量,我可以做这样的事情:

List<Thing> filtered = things.parallelStream().filter(filter1).or(filter2).or(filter3)).collect(Collectors.toList());

但是如何在不混合编程风格的情况下应用未知数量的谓词?因为知道它看起来很丑陋…

最佳答案
我假设你的过滤器是一个类型不同于java.util.function.Predicate,这意味着它需要适应它。一种工作方式是这样的:

things.stream().filter(t -> filtersCollection.stream().anyMatch(f -> f.test(t)));

这导致为每个谓词评估重新创建过滤流的轻微性能损失。为了避免您可以将每个过滤器包装到谓词中并组合它们:

things.stream().filter(filtersCollection.stream().<Predicate>map(f -> f::test)
                       .reduce(Predicate::or).orElse(t->false));

然而,由于现在每个过滤器都在其自己的谓词之后,引入一个更多级别的间接,所以不清楚哪种方法将具有更好的总体性能。

没有适应的关注(如果你的过滤器恰好是一个谓词),问题陈述变得更简单,第二种方法明显胜出:

things.stream().filter(
   filtersCollection.stream().reduce(Predicate::or).orElse(t->true)
);

转载注明原文:如何将多个谓词应用于java.util.Stream? - 代码日志