-2

When I run the code below, StringBuilder instance remains empty.

String[] params = {"v1", "v2"};
StringBuilder sb = new StringBuilder();
Stream.of(params).map(param -> sb.append(param));

However, when I run the same code with forEach instead of map, it behaves as expected (appends array elements to StringBuilder instance):

String[] params = {"v1", "v2"};
StringBuilder sb = new StringBuilder();
Stream.of(params).forEach(param -> sb.append(param));

Why doesn't it change StringBuilder in the first example?

Holger
  • 285,553
  • 42
  • 434
  • 765
Cybex
  • 481
  • 1
  • 6
  • 29
  • 3
    `map` is an intermediary operation, while `forEach` is a terminal operation. Since `Stream`s are evaluated lazily, the intermediary operations are ony triggered thtrough a terminal operation. – Turing85 Sep 21 '20 at 17:47
  • 2
    [What is the difference between intermediate and terminal operations](https://stackoverflow.com/questions/47688418/what-is-the-difference-between-intermediate-and-terminal-operations) – Michał Krzywański Sep 21 '20 at 17:47
  • Thanks for the explanation! – Cybex Sep 21 '20 at 17:50

2 Answers2

3

The reason is that the stream has not been invoked.

String[] params = {"v1", "v2"};
StringBuilder sb = new StringBuilder();
Stream.of(params).map(param -> sb.append(param));

The last statement doesn't run since there is no subsequent method that activates the stream. Try this:

Stream.of(params).map(param -> sb.append(param)).forEach(System.out::println);

Now sb should have the values.

WJS
  • 36,363
  • 4
  • 24
  • 39
1

Streams are evaluated lazily. This means that intermediate operations like Stream::map and Stream::filter are only evaluated when they are triggered through a terminal operation like Stream::forEach or Stream::collect.

We can rewrite the code to make it behave as expected:

String[] params = {"v1", "v2"};
StringBuilder sb = new StringBuilder();
Stream.of(params).map(sb::append).collect(Collectors.toList());
System.out.println(sb.toString());

Ideone demo

I would, however, suggest to use the forEach-example presented in the post, since this reflects the semantics of the code in a concise and clear way.

Turing85
  • 18,217
  • 7
  • 33
  • 58