Java8:Stream如何工作?

时间:2017-08-23 01:55:11

标签: dictionary foreach filter java-8 java-stream

我正在研究Java8 esp Stream API。 但仍然没有得到流和地图的工作方式。

我对流的理解就像 当我使用peek()和forEach()时,结果将是1111 2222,但println()的结果是混合的。

我想如果我使用map()。filter()。map()。filter()然后首先执行map()并返回流并执行下一个filter()并像这样移动到下一个。所以我对这个结果很困惑。

这是我的代码

package exam_20170823;

    import java.io.File;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;

    public class StreamEx2 {
    public static void main(String[] args) {

    File[] fileArr = {
            new File("Ex1.java"),
            new File("Ex1.bak"),
            new File("Ex1.txt"),
            new File("Ex2.java"),
            new File("Ex1")

    };


    /*1) make stream
      2) find filename extension
      3) change 2) to uppercase
      4) remove duplicate
      5) print
    */

    Stream<File> fileStream = Stream.of(fileArr);

    fileStream.map(s->s.getName())
                .filter(s -> s.indexOf(".") != -1)
                .peek(a -> System.out.println(a))
                .map(s -> s.substring(s.indexOf(".")+1).toUpperCase())
                .distinct()  
                .forEach(s -> System.out.println(s));


}

}

这是结果

Ex1.java JAVA Ex1.bak BAK Ex1.txt TXT Ex2.java

我想知道为什么结果不是这样的? - &GT; “Ex1.java,Ex1.bak,Ex1.txt,Ex2.java”首先打印“JAVA,BAK,TXT” 我首先使用peek(),最后使用foreach(),所以我期待 使用peek()后,流将为Ex1.java,Ex1.bak,Ex1.txt,Ex2.java 接下来我使用map()所以它必须有JAVA,BAK,TXT。和 最后使用foreach()所以流的每一个东西都会打印出我所期望的东西,但它太混乱了。有谁能帮我理解为什么?

1 个答案:

答案 0 :(得分:3)

我觉得你在这里混淆了懒惰。不所有元素将通过map,然后全部通过 filter,然后所有被过滤的元素将转到另一个map 1}}。这不是流的工作方式。

处理懒惰。这意味着一次一个元素来自source(在您的情况下是File s的数组),那么该元素将遍历Stream管道的所有阶段(map ,然后是filter,然后是peek);请注意,如果filter失败,则根本不会达到peek。然后第二个元素从源中获取并执行相同的操作,依此类推。

这就是为什么你一次看到每个舞台上的输出。见这个例子:

Stream.of(1, 2, 3, 4)
            .filter(x -> {
                System.out.println("Filering x = " + x);
                return x > 2;
            })
            .map(x -> {
                System.out.println("Mapping x = " + x);
                return x + 1;
            })
            .collect(Collectors.toList());

注意mapping阶段仅在第三个元素上执行,因为前两个不满足Predicate阶段中的filter