Java 8 Streams peek/map without collecting is not giving output.

huangapple go评论79阅读模式
英文:

Java 8 Streams peek/map without collecting is not giving output

问题

以下是要翻译的内容:

"The below code is not printing any values. None of the System.out.println() statements are getting printed. I assumed peek deals with modifying data. Surprisingly the logic inside the peek() is not even getting executed.
If I collect the stream using Collectors I see the desired behavior.

  • Why at least the print statement 1 isn't getting executed?
  • Why isn't the external object (output list) is not getting appended with the desired values?"
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class HelloWorld {
    public static void main(String[] args) {
        List<String> input = new ArrayList<>(Arrays.asList("hello", "bye", "vacation"));
        List<String> output = new ArrayList<>();
        input.stream().peek(x -> {
            System.out.println(x+"inside"); // print statement 1
            if (x.length() > 3) {
                output.add(x.toUpperCase());
            }
        });

        output.forEach(System.out::println); // print statement 2
    }
}
英文:

The below code is not printing any values. None of the System.out.println() statements are getting printed. I assumed peek deals with modifying data. Surprisingly the logic inside the peek() is not even getting executed.
If I collect the stream using Collectors I see the desired behavior.

  • Why at least the print statement 1 isn't getting executed?
  • Why isn't the external object (output list) is not getting appended with the desired values?
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class HelloWorld {
    public static void main(String[] args) {
        List&lt;String&gt; input = new ArrayList&lt;&gt;(Arrays.asList(&quot;hello&quot;, &quot;bye&quot;, &quot;vacation&quot;));
        List&lt;String&gt; output = new ArrayList&lt;&gt;();
        input.stream().peek(x -&gt; {
            System.out.println(x+&quot;inside&quot;); // print statement 1
            if (x.length() &gt; 3) {
                output.add(x.toUpperCase());
            }
        });

        output.forEach(System.out::println); // print statement 2
    }
}

答案1

得分: 3

代码中存在一些问题:

  1. Stream没有使用终端操作关闭,因此没有调用任何流操作。
  2. Stream::peek是主要用于调试的中间操作。
  3. 在流中永远不应该使用任何有副作用或状态的操作 - 调用output.add(x.toUpperCase());不是一个好的做法。
  4. output为空,因此只有在关闭Stream时(参见第1点)才会打印出内容。

您只需要理解Stream API的内容,可以总结如下:

List<String> output = input.stream()              // Stream<String>
	.peek(x -> System.out.println(x + " inside")) // 打印每个值
	.filter(x -> x.length() > 3)                  // 过滤长度大于3的字符串
	.map(x -> x.toUpperCase())                    // 使用map将它们转换为大写
	.collect(Collectors.toList());                // 转换为List - 终端操作
英文:

There are several issues in the code:

  1. The Stream is not closed with a terminal operation, therefore no pipeline operation is invoked.
  2. Stream::peek is an intermediate operation used mainly for debugging.
  3. You should never use any side-effect or stateful operation inside the stream - calling output.add(x.toUpperCase()); is not good.
  4. The output is empty so nothing is printed out as long as the Stream is not closed (see the no. 1).

All you need to understand Stream API is at the package description. Finally, you can conclude into something like:

List&lt;String&gt; output = input.stream()              // Stream&lt;String&gt;
	.peek(x -&gt; System.out.println(x + &quot; inside&quot;)) // print each value
	.filter(x -&gt; x.length() &gt; 3)                  // filter Strings longer than 3 chars
	.map(x -&gt; x.toUpperCase())                    // make them uppercase using map
	.collect(Collectors.toList());                // to List - a terminal operation

答案2

得分: 2

当引用Stream#peek(Consumer)时,会从现有的Stream创建一个新的StatelessOp对象。然而,仅当消耗Stream元素时才会调用StatelessOp对象中的opWrapSink方法。您在任何时候都没有消耗Stream的元素。在文档中的理由是中间操作是懒惰执行的。

寻求懒惰性。许多流操作,如过滤、映射或去重,可以以惰性方式实现,从而提供了优化的机会。例如,"查找具有三个连续元音字母的第一个字符串"不需要检查所有输入字符串。流操作分为中间操作(生成流)和终端操作(生成值或副作用)。中间操作始终是惰性的。

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

英文:

When Stream#peek(Consumer) is referenced, a new StatelessOp object is created from the existing Stream. However, the method from the StatelessOp object called opWrapSink is only called when the Stream elements are consumed. You are not consuming the elements of the Stream at any point. In the documentation the reasoning is that intermediate operations are done lazily.

> Laziness-seeking. Many stream operations, such as filtering, mapping,
> or duplicate removal, can be implemented lazily, exposing
> opportunities for optimization. For example, "find the first String
> with three consecutive vowels" need not examine all the input strings.
> Stream operations are divided into intermediate (Stream-producing)
> operations and terminal (value- or side-effect-producing) operations.
> Intermediate operations are always lazy.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

答案3

得分: 0

你的流缺少终端操作符,所以它不会执行任何操作。

请参阅 https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

> 中间操作返回一个新的流。它们始终是延迟执行的;执行中间操作,如 filter(),实际上并不执行任何过滤操作,而是创建一个新的流,当遍历时,它包含与给定谓词匹配的初始流的元素。只有在管道的终端操作被执行之后,才会开始遍历管道源。

.collect 是一个终端操作符,这就解释了为什么当你用 collect 替换 close 时它起作用。

英文:

You lack a terminal operator on your stream, so nothing will happen with it.

See https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html:

> Intermediate operations return a new stream. They are always lazy; executing an intermediate operation such as filter() does not actually perform any filtering, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given predicate. Traversal of the pipeline source does not begin until the terminal operation of the pipeline is executed.

The .collect is a terminal operator which explains why it works when you replace close with collect.

huangapple
  • 本文由 发表于 2020年7月28日 05:57:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/63124205.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定