【问题标题】:How to apply a collection of filters to a Java stream?如何将过滤器集合应用于 Java 流?
【发布时间】:2021-10-22 02:27:15
【问题描述】:

如何将谓词集合应用于 Java 流?

以下代码将说明我的想法:

final Collection<Predicate<MyObject>> filters = getFilters();
final Stream<MyObject> oStream = getMyObjectStream();
oStream
   .filterAll(filters) // <- this one doesn't exist
   .forEach(System.out::println);

我目前正在使用带有经典循环的函数.filter(m -&gt; applyAllFilters(m, filters)),但想知道是否有更“流式”的方式?

boolean applyAllFilters(final MyObject m, final Collection<Predicate<MyObject>> filters) {
   Iterator Predicate<MyObject> iter = filters.iterator();
   while(iter.hasNext()) {
      Predicate<MyObject> p = iter.next();
      if (!p.test(m)) {
         return false;
      }
   } 
  return true;
}

【问题讨论】:

  • 删除Collection&lt;Predicate&gt; 并酌情使用Predicate.and()Predicate.or() 将它们连接在一起。 getFilters() 应该返回这个 Predicate,而不是它们的集合。

标签: java java-8 java-stream


【解决方案1】:

您可以简单地将所有谓词简化为一个与所有谓词进行与运算的谓词,如下所示:

oStream
    .filter(filters.stream().reduce(Predicate::and).orElseThrow())
    .forEach(System.out::println);

或者,如果您希望过滤器列表在某些情况下为空,您可以这样做:

oStream
    .filter(filters.stream().reduce(o -> true, Predicate::and))
    .forEach(System.out::println);

【讨论】:

  • Predicate::and 是否在遇到第一个 false 时停止?我想是的。
  • @stwissel 是的,the docs 说它返回“表示此谓词与另一个谓词的短路逻辑与的组合谓词”
  • 是的。 Predicate::and 是两个谓词的简单 &amp;&amp;,因此它的计算是惰性的。您实际上可以检查实现,即:return (t) -&gt; test(t) &amp;&amp; other.test(t);
【解决方案2】:

您可以预先创建一个满足所有条件的过滤器。

假设您有三个Predicate &lt;MyObject&gt; a, b, c。无论oStream如何,它们都可以按如下方式组合。

Predicate<MyObject> allFilter = e -> a.test(e) && b.test(e) && c.test(e);

所以你可以这样做。

Predicate<MyObject> filterAll = filters.stream()
    .reduce(Predicate::and).orElse(e -> true);

oStream
   .filter(filterAll)
   .forEach(System.out::println);

【讨论】:

  • 你确定吗?谓词应用于 oStream 的成员,这些成员在预创建时不可用。所以Predicate::and 没有得到输入。还是我错过了什么?
【解决方案3】:

您可以使用循环来应用过滤器:

final Collection<Predicate<MyObject>> filters = getFilters();

Stream<MyObject> oStream = getMyObjectStream();
for(Predicate<MyObject> p : filters) {
    oStream = oStream.filter(p);
}
oStream.forEach(System.out::println);

【讨论】:

    猜你喜欢
    • 2017-08-23
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多