在scala中,这些方法工作正常,但在java9中,dropWhile的工作方式与我想的不同.
以下是takeWhile的示例
Stream.of("a", "b", "c", "de", "f", "g", "h") .peek(System.out::println) .takeWhile(s -> s.length() <= 1) .collect(Collectors.toList());
输出很好:a,b,c,de,[a,b,c]它不处理"de"之后的元素,所以它按预期工作
但是DropWhile以我期望的不同方式工作:
Stream.of("a", "b", "c", "de", "f", "g", "h") .peek(s -> System.out.print(s + ", ")) .dropWhile(s -> s.length() <= 1) .collect(Collectors.toList());
输出为:a,b,c,de,f,g,h,[de,f,g,h]
因此它不会在"de"元素之后停止,它正在处理整个集合.
为什么要处理整个系列?我知道,需要采取所有元素并将其收集到列表中,但不应该在"de"元素之后停止处理吗?
看来,对于如何peek
运作存在根本的误解.它与下一个随后的链接操作无关,例如dropWhile
,但它背后的整个Stream管道.它并没有区分"处理元素"和"占用所有元素".
所以简单的代码
Stream.of("a", "b", "c", "de", "f", "g", "h") .peek(System.out::println) .collect(Collectors.toList());
"获取所有元素",但在将它们从Stream源传递到收集器时打印它们.
在您的示例中,无论是否将元素传递给谓词dropWhile
或直接传递给它,它都没有区别,Collector
在任何一种情况下,它都会被peek
放在两者之前的操作报告.
如果你使用
Stream.of("a", "b", "c", "de", "f", "g", "h") .dropWhile(s -> { System.out.println("dropWhile: "+s); return s.length() <= 1; }) .peek(s -> System.out.println("collecting "+s)) .collect(Collectors.toList());
相反,它会打印出来
dropWhile: a
dropWhile: b
dropWhile: c
dropWhile: de
collecting de
collecting f
collecting g
collecting h
显示dropWhile
在第一个未接受的元素之后,谓词的评估如何停止,而向该元素的转移Collector
开始.
这不同于takeWhile
其中两个,谓词评价和集电极,停止消耗元件,所以没有消费者左和整个流管道可以停止迭代源.
这是预期的行为,与scala中的工作方式相同,dropWhile处理整个流.
dropWhile与takeWhile相反.takeWhile在条件变为false时停止处理.dropWhile处理整个流,但只有在条件为真时才传递任何元素.一旦条件变为false,dropWhile会传递所有剩余元素,无论条件是真还是假.