首页 > 解决方案 > Java 8 流执行

问题描述

你能解释一下下面代码的执行过程吗?主要是sorted方法。

Stream.of("d2", "a2", "b1", "b3", "c")
    .sorted((s1, s2) -> {
        System.out.printf("sort: %s; %s\n", s1, s2);
        return s1.compareTo(s2);
    })
    .filter(s -> {
        System.out.println("filter: " + s);
        return s.startsWith("a");
    })
    .map(s -> {
        System.out.println("map: " + s);
        return s.toUpperCase();
    })
    .forEach(s -> System.out.println("forEach: " + s));

输出:

sort:    a2; d2
sort:    b1; a2
sort:    b1; d2
sort:    b1; a2
sort:    b3; b1
sort:    b3; d2
sort:    c; b3
sort:    c; d2
filter:  a2
map:     a2
forEach: A2
filter:  b1
filter:  b3
filter:  c
filter:  d2

谢谢,参考:https ://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/

标签: javajava-8java-stream

解决方案


因此,Java8尝试通过对任何给定输入尽快执行所有高阶函数来加快执行速度。也就是说,例如,如果您map在列表中连续调用两次,那么它将只访问列表中的每个元素一次。这加快了速度,因为它从 2 次通过列表变为 1 次。为了说明,举这个简单的例子:

Stream.of(1, 2, 3)
    .map(s -> {
        System.out.println("map: " + s.toString());
        return s;
    })
    .map(s -> {
        System.out.println("map: " + s.toString());
        return s;
    })

这将打印:

1
1
2
2
3
3

因为“触摸”列表中的每个元素一次比完全遍历两个maps 的列表要快!

就您的示例而言,让我们逐个进行:

sort:    a2; d2
sort:    b1; a2
sort:    b1; d2
sort:    b1; a2
sort:    b3; b1
sort:    b3; d2
sort:    c; b3
sort:    c; d2

所有的排序都需要同时发生,而且这一切都需要首先发生。这是因为计算机在排序完成之前无法知道哪个元素将在哪个位置(即它不能在同一个列表位置上映射两次,因为排序可能会改变它)

接下来,你基本上有这个:

Stream.of("a2", "b1", "b3", "c", "d2")
    .filter(s -> {
        System.out.println("filter: " + s);
        return s.startsWith("a");
     })
    .map(s -> {
        System.out.println("map: " + s);
        return s.toUpperCase();
    })
    .forEach(s -> System.out.println("forEach: " + s));

现在,为了最大限度地减少通过列表的次数,Java 将遍历列表中的每个元素并执行filter然后执行map然后执行forEach. 这是因为这些都不依赖于元素的位置。换句话说,Java 认为它可以对每个元素执行所有这些操作,而不是对每个函数遍历整个列表三次!

现在:

filter:  a2
map:     a2
forEach: A2

我们filter是第一个元素,然后我们map覆盖它,然后我们进行最终forEach打印。

filter:  b1
filter:  b3
filter:  c
filter:  d2

这些都被过滤掉了,所以其余的函数不会被调用!


推荐阅读