首页 > 解决方案 > Java 8 Stream 如果不执行收集功能,则过滤和映射功能不起作用

问题描述

public static void main(String[] args) throws Exception {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");

    // below code does not work
    list.stream().filter(new Predicate<String>() {
        @Override
        public boolean test(String s) {
            System.out.println("1:test:&quot; + s);
            return true;
        }
    }).map(s -> {
        System.out.println("1:map:&quot; + s);
        return s;
    });
    
    // below code works
    list.stream().filter(new Predicate<String>() {
        @Override
        public boolean test(String s) {
            System.out.println("2:test" + s);
            return true;
        }
    }).map(s -> {
        System.out.println("2:map" + s);
        return s;
    }).collect(Collectors.toList());
}

上述代码的输出为:</p>

2:test1
2:map1
2:test2
2:map2
2:test3
2:map3
2:test4
2:map4

我不知道为什么它第一次没有工作。

标签: javajava-stream

解决方案


只有在执行doSomethinglambdap -> doSomething(p)时才会调用 lambda 中的 。该语句的简单存在并不能保证执行,而普通(不是 lambda)语句 doSomething(x)可以保证执行。

mapfilter是中间操作,而collect是终端操作。Stream对于每个中间操作,都会返回一个新的流对象( like的任何实现StatelessOpStatefulOp或流 like 的原始特化IntStreamLongStream),该对象存储任何信息,如您的情况中的映射或过滤函数。实际执行不会在这里发生。

流评估发生在evaluate方法的调用中。现在,如果您看到任何终端操作,它将调用此evaluate方法。这是您作为参数传递给中间操作的 lambdas 应用于流元素。这就是为什么说流被延迟评估的原因->评估仅从应用终端操作开始。

因此,您的第一个代码块不起作用,因为没有终端操作,并且您传递的 lambdas 没有执行。但是在第二个代码块中,您调用终端操作并评估流。另请注意,不需要对每个流元素执行中间操作 ->参考

您可以在ReferencePipeline.


推荐阅读