【问题标题】:Multiple filters applied to a single list in Java 8+多个过滤器应用于 Java 8+ 中的单个列表
【发布时间】:2020-02-02 14:16:03
【问题描述】:

如何在 Java 8 中将“过滤器列表”传递给流,而不是如下例所示单独应用它们?

https://howtodoinjava.com/java8/stream-multiple-filters-example/

目的是动态创建过滤器列表,一种方法是遍历过滤器列表并将其应用于要过滤的列表。

还有什么想法吗?

更新:

感谢谓词的评论:

   final Predicate<?> predicate = new Predicate<?>() {

        @Override 
        public boolean test(Object object) {
            return false; //TODO: Implement first predicate
        }
    } ;

    predicate.and(...); //Implement another predicate.

问候

~M

【问题讨论】:

  • 您可以使用例如Predicate::and 方法链接Predicates。
  • 不错,我会试试的,谢谢你的评论。
  • 如前所述,可以制作一个由.and 谓词链组成的谓词。但是,.filter 链具有相同的效果,因为它们是在最终流操作发生(收集/减少/forEach)之前收集的。
  • 没错,但是我想为管理员提供一个易于理解的解决方案,说明如何添加更多过滤器(谓词)。

标签: java list arraylist lambda java-8


【解决方案1】:

您可以使用andor 运算符链接谓词。您是否希望您的组合谓词成为匹配对象的谓词,该对象与 所有 组件谓词匹配,还是仅匹配其中一个?如果要模拟filter 调用链:

someStream.filter(...)
            .filter(...)
            .filter(...)
            .filter(...)

那么你应该使用and

根据您的选择,您可以使用以下任一方法:

public static <T> Predicate<T> combineFilters(List<Predicate<T>> filters) {
    return filters.stream().reduce(Predicate::and).orElse(x -> true);
}

public static <T> Predicate<T> combineFilters(List<Predicate<T>> filters) {
    return filters.stream().reduce(Predicate::or).orElse(x -> false);
}

用法:

someStream.filter(combineFilters(aListOfFilters))
    ...

【讨论】:

  • 是的,这确实是一个很好的解决方案,在真正链接谓词对我来说只有将所有链接都链接到“and”(对于我的特定问题)才有意义
  • ...reduce(Predicate::or)的小修正,你必须使用x-&gt;false
  • @Aman 不错!
【解决方案2】:

假设你有一个谓词生成器,比如这个测试生成器

    Supplier<Integer> seed = () -> (int) (Math.random() * 9 + 2); // in [2, 11]
    Supplier<Predicate<Integer>> generator = () -> {
        int seedNow = seed.get();
        return (Integer value) -> (value % seedNow == 0);
    };

你知道,它提供了一个有限的过滤器序列,

你最好在实际过滤之前积累它们

    Predicate<Integer> cumulative = Stream.generate(generator)
            .limit(5)
            .reduce(Predicate::and).orElse((value) -> true);

然后利用

    List<Integer> output = IntStream.range(0, 300)
            .boxed()
            .filter(cumulative)
            .collect(Collectors.toList());

【讨论】:

    【解决方案3】:
       List<Integer> numbers = Arrays.asList(1,2,null,3,0,0,8);
    
       Predicate<Integer> fitlerPredicate = i -> i != null && i > 0;
        List<Integer> collect = numbers.stream().filter(fitlerPredicate).collect(Collectors.toList());
        collect.forEach(System.out::println);
    

    您可以使用 && 运算符链接过滤条件列表并将该值传递给流 api 的过滤操作

    【讨论】:

      猜你喜欢
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 2015-06-08
      • 2020-09-03
      • 2014-10-21
      • 2021-01-12
      • 2017-10-04
      • 2018-09-03
      相关资源
      最近更新 更多