代码之家  ›  专栏  ›  技术社区  ›  Alkis Mavridis

Java流:对链接使用可选的filter()操作

  •  6
  • Alkis Mavridis  · 技术社区  · 7 年前

    注:此问题是 有关 java.util.Optional

    在处理流时,我经常使用如下逻辑:

     Stream<FooBar> stream = myInitialStream();
     if (needsFilter1) stream = stream.filter(c -> whatever1());
     if (needsFilter2) stream = stream.filter(c -> whatever2());
     ...
     return stream.collect(toList());
    

    我试图实现的是使用链接将上面的代码转换为单个表达式。我觉得这更具可读性和直截了当。 到目前为止,我发现实现这一目标的唯一途径是:

    return myInitialStream()
           .filter(needsFilter1? c->whatever1() : c->true)
           .filter(needsFilter2? c->whatever2() : c->true)
           .collect(toList());
    

    尽管如此,这仍会对这些琐碎的问题产生不必要的影响 c->true lamdas,在扩展时可能会产生一些性能成本。

    所以我的问题是:有没有更好的方法来生成包含可选筛选的链式流表达式?

    更新:也许我说得不够清楚,但我的问题是找到一个 . 如果我必须使用多个语句(例如,初始化一个谓词),我还可以使用问题的第一个代码块,这基本上是相同的。

    2 回复  |  直到 7 年前
        1
  •  11
  •   Nikolas Charalambidis    7 年前

    根据使用的条件链接谓词 Predicate::and 返回一个新谓词。

    Predicate<FooBar> predicate = c -> whatever();
    
    if (condition1) { predicate = predicate.and(c -> whatever1()); }
    if (condition2) { predicate = predicate.and(c -> whatever2()); }
    
    List<FooBar> dest = list.stream()
        .filter(predicate)
        .collect(Collectors.toList());
    

    当更新请求单个表达式时。你 需要 无论如何,映射到谓词的条件的源。使用数据结构 Map<Supplier<Boolean>, Predicate<Integer>> ,其中键是 Supplier 指决定某个值是否为( Predicate<FooBar> )应使用。

    谓词<福巴> Predicates 具有 谓词::and ,他们的 Supplier<Boolean> 返回 true (条件有效)。

    Map 其中:

    Map<Supplier<Boolean>, Predicate<FooBar>> map = new HashMap<>();
    map.put(() -> needsFilter1, c -> whatever1());
    map.put(() -> needsFilter2, c -> whatever2());
    ...
    

    这是一张单人票 Stream 声明:

    List<Integer> dest = list
            .stream()
            .filter(map.entrySet()                            // filter with a predicate ...
                    .stream()
                    .filter(e -> e.getKey().get())            // .. where a condition is 'true'
                    .map(Entry::getValue)                     // .. get Predicates
                    .reduce(i -> true, (l, r) -> l.and(r)))   // .. reduce them using AND
            .collect(Collectors.toList());               
    
        2
  •  4
  •   Andrew    7 年前

    我的解决方案有点晚了,不管怎样,我还是把它留在这里。

    我有一个想法,写一个建设者来建造一个综合体 Predicate 但最终还是上了一堂课 FilterCondition 和一种方法 FilterCondition.combine .

    Stream.of("123", "1", "12345", "", "12", "", "2")
        .filter(FilterCondition.<String>combine(
                    FilterCondition.of(() -> true, s -> s.contains("3")),
                    FilterCondition.of(() -> true, s -> s.contains("2")),
                    FilterCondition.of(() -> false, s -> s.isEmpty())
                ).toPredicate())
        .collect(Collectors.toList());
    

    通过静态导入 FilterCondition.of FilterCondition.combine, 看起来会更好。

    Stream.of("123", "1", "12345", "", "12", "", "2")
        .filter(combine(
                    of(() -> true, s -> s.contains("3")),
                    of(() -> true, s -> s.contains("2")),
                    of(() -> false, String::isEmpty)
                ).toPredicate())
        .collect(Collectors.toList());
    

    FilterCondition<T> 基本上是一个 Predicate<T> predicate 应该应用。

    需要一些 过滤条件

    class FilterCondition<T> {
        private final Supplier<Boolean> filterEnabled;
        private final Predicate<T> predicate;
    
        private FilterCondition(Supplier<Boolean> filterEnabled, Predicate<T> predicate) {
            this.filterEnabled = filterEnabled;
            this.predicate = predicate;
        }
    
        public static <T> FilterCondition<T> of(Supplier<Boolean> filterEnabled, Predicate<T> predicate) {
            return new FilterCondition<>(filterEnabled, predicate);
        }
    
        @SafeVarargs
        public static <T> FilterCondition<T> combine(FilterCondition<T>... conditions) {
            return new FilterCondition<>(
                    () -> true,
                    Arrays.stream(conditions).filter(i -> i.filterEnabled.get()).map(i -> i.predicate).reduce(Predicate::and).orElse(t -> true)
            );
        }
    
        public Predicate<T> toPredicate() {
            return predicate;
        }
    
    }
    
    推荐文章