java - 在无限流上调用 .map()?

标签 java lambda functional-programming java-stream functional-interface

根据 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 急切地询问下一个项目(只要之前的不为空),以及 生成流,为了提供下一个项目,可能需要等待等待用户发送更多输入的供应商。

但是应该说,这里不应该使用mapmap 不应有副作用 - 它应该用于将一种类型的项目映射到另一种类型的项目。我认为此示例仅用作学习辅助工具。更简单直接的方法是使用 BufferedReader's method lines()它为您提供来自缓冲阅读器的行的有限 Stream

关于java - 在无限流上调用 .map()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51028370/

相关文章:

java - 当我尝试运行 .jar 时,出现 java.library.path 中没有库的异常

java - 如何在撰写邮件功能中将表面 View 与媒体记录器连接

c# - 已编译的 lambda 表达式用作属性 getter 和 setter : wrong benchmarking method or wrong lambda expression construction?

c++ - 在 C++11 的 lambda 中使用封闭函数中的模板类型可以吗?

c# - 嵌套对象上的条件 Linq 选择

java - ViewPager.setAdapter() 抛出 NullPointException; viewPager 和 pagerAdapter 似乎不为空?

java - Spring Security 超时时将用户重定向到登录页面

javascript - 获取多边形矢量积的函数方法

haskell - 转置嵌套数据结构

c# - 编写一个 C# 版本的 Haskell 无限斐波那契数列函数