Java 8流 - 链中的每一步评估整个输入或项目是否通过?

djh*_*rld 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());
Run Code Online (Sandbox Code Playgroud)

在幕后它的工作方式如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")
Run Code Online (Sandbox Code Playgroud)

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")
Run Code Online (Sandbox Code Playgroud)

ski*_*iwi 8

它的工作方式与选项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);
    }
}
Run Code Online (Sandbox Code Playgroud)

你在这里看到的是:

  • 作为输入a Collection<String>,您的输入.
  • 一个Function<String, String>符合map().
  • 一个Predciate<String>符合filter().
  • Collector<String, ?, List<String>>符合collect(),这是对类型的元素进行操作的集电极String,使用中间存储?和给出List<String>.

然后它做的是:

  • Supplier<List<String>>收集器的供应商(类型:)获取新列表.
  • 循环遍历输入的每个元素,在操作时在内部完成Stream<String>,我在Collection<String>这里使用expliciteness,这样我们仍然可以连接到旧的Java 7世界.
  • 应用您的映射功能.
  • 测试过滤器谓词.
  • 获取累加器(类型:BiConsumer<List<String>, String>)的的toList收藏家,这是二进制消费者认为需要作为参数的List<String>它已经和String它要补充.
  • 喂我们listin蓄能器.

请仔细注意,实际的实现要先进得多,因为操作可以按任何顺序发生,并且可以发生多个操作,等等.


Roh*_*ain 5

流的一个好处是对中间操作的惰性评估.这意味着,当collect()在这种情况下执行终端操作时,它要求来自先前中间操作的元素 - filter()其依次从中获取元素map(),该元素依次对第一元素进行操作list.stream().所有元素都遵循相同的流程.所以是的,执行更像是选项B.

此外,由于返回的收集器Collectors.toList()是有序的,因此保证元素按顺序执行.在某些情况下,当UNORDERED为收集器设置特性时,评估可能会出现故障.