1

I started working with streams and facing below issue:

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(10);
al.add(20);
al.add(30);

al.stream().forEach(System.out::println); // This works

al.stream().map(System.out::println); // This fails with error as "Incompatible types: expected not void but compile-time declaration for method reference has void return type"

Can someone please explain this?

ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • 1
    `map` takes a `Function` that transforms the stream's element type into something else. Can the `void`-returning `println` do that? – ernest_k Dec 03 '19 at 08:39
  • 1
    ```map``` expects a function. ```System.out.println()``` is a consumer and not a function – D. Lawrence Dec 03 '19 at 08:39
  • `map` returns a value. So it accepts a function that returns a value. System.out.println() doesn't return anything. – dxjuv Dec 03 '19 at 08:46
  • Or, in even simpler words, it's because `map` is a different method than `forEach`, with an entirely different purpose and no reason to behave like `forEach`. – Holger Dec 03 '19 at 14:52

2 Answers2

4

In a plain English kind of way:

forEach applies a method that has a side effect to each element of your stream, it is a terminal operation and it does not return anything:

...
.forEach(thisElement -> doThatWith(thisElement))

examples:

.forEach(thisElement -> System.out.println(thisElement))
.forEach(thisElement -> aList.add(thisElement))

map applies a method that transform each element of your stream into another object and returns a Stream<NewObjectClass>:

...
.map(thisElement -> transformIntoAnotherElement(thisElement))

Examples:

.map(thisElement -> String.valueOf(thisElement)) // returns Stream<String>
.map(thisElement -> new MyObject(thisElement)) // returns Stream<MyObject>
Bentaye
  • 9,403
  • 5
  • 32
  • 45
2

map() transforms a Stream of elements of one type to a Stream of elements of another type.

Therefore, you must pass to map() a Function that transforms elements of the original type to the new type. System.out::println doesn't fit the Function functional interface, since it has a void return type.

And even if you passed a valid Function to map(), it would not be applied to any elements of the Stream, since your second Stream pipeline has no terminal operation.

Eran
  • 387,369
  • 54
  • 702
  • 768