根据 Javadocs for SE 8 Stream.map() 做以下事情
Returns a stream consisting of the results of applying the given function to the elements of this stream.
但是,我正在阅读的一本关于网络的书(Learning Network Programming with Java,Richard M. Reese)在回显服务器中大致实现了以下代码片段。
Supplier<String> inputLine = () -> {
try {
return br.readLine();
} catch(IOException e) {
e.printStackTrace();
return null;
}
};
Stream.generate(inputLine).map((msg) -> {
System.out.println("Recieved: " + (msg == null ? "end of stream" : msg));
out.println("echo: " + msg);
return msg;
}).allMatch((msg) -> msg != null);
这应该是一种功能性的方式来完成让用户输入打印到套接字输入流。它按预期工作,但我不太明白如何。是不是因为 map 知道流是无限的,所以它会在新的流 token 可用时延迟执行?似乎向当前由 map 迭代的集合添加一些东西是一个小黑魔法。有人可以帮我了解幕后发生的事情吗?
以下是我重申这一点的方式,以避免混淆 map 的使用。我相信作者试图避免无限循环,因为您无法跳出 forEach。
Stream.generate(inputLine).allMatch((msg) -> {
boolean alive = msg != null;
System.out.println("Recieved: " + (alive ? msg : "end of stream"));
out.println("echo: " + msg);
return alive;
});
最佳答案
流是惰性的。将它们视为链条中的 worker ,将桶相互传递。懒惰在于,如果前面的 worker 要求下一个桶,他们只会向后面的 worker 索要下一个桶。
所以最好将其视为 allMatch
- 作为最终操作,因此急切 - 向 map
流请求下一个项目,而 map
流向 generate
流询问下一个项目,generate
流将转到其供应商,并在该项目到达后立即提供该项目。
当 allMatch
停止请求项目时它停止。当它知道答案时,它就会这样做。此流中的所有项目都不为空吗?一旦 allMatch
收到一个为 null 的项目,它就知道答案为 false
,并且将完成并且不再要求任何项目。因为流是无限的,否则它不会停止。
所以你有两个因素导致它以它的方式工作 - 一个是 allMatch
急切地询问下一个项目(只要之前的不为空),以及 生成
流,为了提供下一个项目,可能需要等待等待用户发送更多输入的供应商。
但是应该说,这里不应该使用map
。 map
不应有副作用 - 它应该用于将一种类型的项目映射到另一种类型的项目。我认为此示例仅用作学习辅助工具。更简单直接的方法是使用 BufferedReader
's method lines()
它为您提供来自缓冲阅读器的行的有限 Stream
。
关于java - 在无限流上调用 .map()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51028370/