【问题标题】:Java8 : How Stream works?Java8:流如何工作?
【发布时间】:2017-08-23 01:55:10
【问题描述】:

我正在学习 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

只是我想知道为什么结果不是这样? -> "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() 所以流的每一件事都将被打印出我所期望的,但它是如此混乱。有谁能帮我理解为什么?

【问题讨论】:

  • 你在哪里看到11112222???
  • 不是字面上我看到的 1111 2222 只是我的意思是输出顺序:)
  • 输出的顺序看起来不错。如果您有不清楚的地方,请更具体和准确。

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


【解决方案1】:

我认为您在这里混淆了懒惰。并非所有元素都将通过map,然后所有filter,然后所有被过滤的元素都将通过另一个map。这不是流的工作方式。

处理是惰性。这意味着一次一个元素取自source(在您的情况下是Files 的数组),然后该元素经过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 阶段是如何仅在第三个元素处执行的,因为前两个不满足filter 阶段中​​的Predicate

【讨论】:

  • 你的解释和这个例子真的帮助我理解了懒惰是如何工作的。非常感谢!
猜你喜欢
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
相关资源
最近更新 更多