Java 8 流 - 链中的每个步骤都针对整个输入进行评估,还是项目通过?

标签 java java-8 java-stream

假设我有这个简单的程序

    List<String> input = Arrays.asList("1", "2", "3");
    List<String> result = input.stream()
            .map(x -> x + " " + x)
            .filter(y -> !y.startsWith("1"))
            .collect(Collectors.toList());

在幕后,它是像 a) 还是 b) 一样工作

一个

map
  "1" + " " + "1"
  "2" + " " + "2"
  "3" + " " + "3"
filter
  "1 1" does not begin with "1"? = false
  "2 2" does not begin with "1"? = true
  "3 3" does not begin with "1"? = true
collect
  add "2 2" to list
  add "3 3" to list
result = List("2 2", "3 3")

B

map
  "1" + " " + "1"
filter
  "1 1" does not begin with "1"? = false
map
  "2" + " " + "2"
filter
  "2 2" does not begin with "1"? = true
collect
  add "2 2" to list
map
  "3" + " " + "3"
filter
  "3 3" does not begin with "1"? = true
collect
  add "3 3" to list
result = List("2 2", "3 3")

最佳答案

它的工作方式与选项 B 类似,不一定完全按照那个顺序,但更重要的是它一次对一个元素执行所有操作。

这背后的原因是变量只通过流一次,所以当您现在拥有该元素时,您需要执行所有操作,因为一旦元素通过,它就永远消失了(从流的角度)。

在线性设置中,您的代码非常非常粗略地等同于以下代码,这是一个非常简化的版本,但我希望您明白这一点:

Collection<String> input = Arrays.asList("1", "2", "3");
Function<String, String> mapper = x -> x + " " + x;
Predicate<String> filter = y -> !y.startsWith("1");
Collector<String, ?, List<String>> toList = Collectors.toList();

List<String> list = ((Supplier<List<String>>)toList.supplier()).get();
for (String in : input) {
    in = mapper.apply(in);
    if (filter.test(in)) {
        ((BiConsumer<List<String>, String>)toList.accumulator()).accept(list, in);
    }
}

你在这里看到的是:

  • 作为输入 Collection<String>的输入。
  • A Function<String, String>匹配您的 map() .
  • A Predciate<String>匹配您的 filter() .
  • A Collector<String, ?, List<String>>匹配您的 collect() ,这是一个对 String 类型的元素进行操作的收集器, 使用中间存储 ?并给出 List<String> .

然后它做的是:

  • 从收集器的供应商(类型:Supplier<List<String>>)处获取新列表。
  • 循环遍历输入的每个元素,在对 Stream<String> 进行操作时在内部完成,我正在使用 Collection<String>这里是为了明确,这样我们仍然可以连接到旧的 Java 7 世界。
  • 应用您的映射函数。
  • 测试您的过滤谓词。
  • 获取 BiConsumer<List<String>, String> 的累加器(类型:toList)收集器,这是将 List<String> 作为参数的二进制消费者它已经有了,String它想添加。
  • 喂我们的 listin到蓄能器。

请非常小心地注意,实际的实现要先进得多,因为操作可以按任何顺序发生,也可以发生多个,等等。

关于Java 8 流 - 链中的每个步骤都针对整个输入进行评估,还是项目通过?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22736122/

相关文章:

java - Junit 根据执行环境(如 local/dev(200/403))测试 spring-rest 服务中的访问被拒绝响应

java - 模式 MM/yy 的 DateTimeFormatter

Java 8 流操作

java - 堆栈溢出错误-java

java - Stream<String> 转换为 Stream<Character>

java - Stream.forEach 中的多行代码

java - Java8中分组的复杂性

java - 使用 CompletableFuture.supplyAsync 返回多个值

java - 由于某种原因,动态更改程序中的 Jlabel 会导致它发送大量错误,但不会崩溃

java - 如果我只是在 Kotlin 中编写,我是否需要为我的 Android Studio 升级到 Java 8?