What does java8 stream map do here?

I was confused by the difference between map() and forEach() method in java8 thread. For instance,

 List<String> strings = Lists.newArrayList("1", "2"); Map<String, String> map = Maps.newHashMap(); strings.stream().map(s->map.put(s, s)); System.out.println(map); 

Here I got empty output, but if I changed the map to forEach() same way

 List<String> strings = Lists.newArrayList("1", "2"); Map<String, String> map = Maps.newHashMap(); strings.stream().forEach(s->map.put(s, s)); System.out.println(map); 

I can get

{1 = 1, 2 = 2}

Why didn't he just run the map() method? What is the difference between the two?

+7
source share
4 answers
 strings.stream().map(s->map.put(s, s)); 

does nothing, since the stream pipeline is not processed until you complete the terminal operation. Therefore, the Map remains blank.

Adding a terminal operation to the stream pipeline will execute map.put(s, s) for each Stream element required by the terminal operation (for some terminal operations, only one element is required, while others require all Stream elements).

On the other hand, the second thread:

 strings.stream().forEach(s->map.put(s, s)); 

ends with a terminal operation - forEach - that runs for each Stream element.

However, both fragments are used incorrectly by Stream s. To populate a Collection or Map based on the contents of the Stream , you must use collect() , which can create a Map or Collection and populate it as you like. forEach and Map have different goals.

For example, to create a Map :

 List<String> strings = Lists.newArrayList("1", "2"); Map<String, String> map = strings.stream() .collect(Collectors.toMap(Function.identity(), Function.identity())); System.out.println(map); 
+21
source

The difference is as follows:

  • The idea forEach() is to "work" with each element of the base collection (using a side effect ), whereas
  • map() is the application of the method to each object and the transfer of the result to a new stream

This is also the reason why your stream().map() does not lead to anything because you are discarding the new stream created by calling map() !

In this sense, the signatures of the two methods tell you that:

 void forEach(BiConsumer<? super K,? super V> action) 

Performs this action for each record on this card until all records are processed.

vs

  <R> Stream<R> map(Function<? super T,? extends R> mapper) 

Returns a stream consisting of the results of applying this function to the elements of this stream.

And for the record: only map() is the stream method - forEach() exists for both streams and collections / Iterables.

+7
source

The documentation for each instance of the Stream method indicates whether the method is an intermediate operation or a terminal operation. Only terminal operations will cause a flow estimate. Intermediate operations cannot be performed unless it is required for the subsequent operation of the terminal.

This can increase efficiency, especially when the operation of the terminal is a short circuit operation, for example findAny() . It is not necessary to perform a pipeline with a complex set of intermediate operations for additional elements after the corresponding element is found.

In your case, forEach() is a terminal operation; this causes the pipeline to execute. map() is an intermediate operation; he should not do anything unless it is required for the subsequent operation of the terminal.

0
source

You have to use

stream().collect(Collectors.toMap(s -> s,s -> s)

... or something along these lines instead of stream().map(...)

-1
source

Source: https://habr.com/ru/post/1270669/


All Articles