1

I was trying to answer this question, but I did not because I don't understand Streams well enough. Please tell me if my explanation is correct or not.

My answer :

import java.util.Arrays;
import java.util.stream.Stream;

public class Temp {
    public static void main(String [] args){
        String [] input = {"1,2", "3,4", "5"};
        String [] expected = {"1", "2", "3", "4", "5"};

        String [] actual = Stream.of(input)
                .flatMap(s -> Arrays.stream(s.split(",")))
                .toArray(String [] :: new);

        //Testing - Runs only when assertions are enabled for your JVM. Set VM args = -ea for your IDE.
        assert Arrays.equals(actual, expected) : "Actual array does not match expected array!";
    }
}

My explanation :

1 - Take a stream of elements (Strings in this example) and pass one element at a time to flatMap.

QUESTION - Is this actually one element at a time ?

2 - flatMap takes a Function which converts an element into a Stream. In the example, the function takes a String ("1,2") and converts it into a stream of multiple Strings ("1", "2"). The stream of multiple strings is generated by Arrays.stream(an array) which we know takes an array and converts it into a stream. That array was generated by s.split(","). All other elements are processed and put into this one stream.

QUESTION - Does flatMap return one Stream for all elements in input array OR one Stream per element of input array ?

3 - toArray takes elements in the single stream it got from flatMap and puts them into one array.

MasterJoe
  • 2,103
  • 5
  • 32
  • 58
  • (1) Yes. (2) The `Function` returns one stream per element in the original stream, allowing `flatMap` to return one stream containing all the "flattened" elements. (3) Too broad a question; to really understand how streams work I suggest looking at the source code. – Slaw Mar 05 '20 at 06:48
  • Try this - `String[] actual = Stream.of(input) .flatMap(s -> Arrays.stream(s.split(","))) .peek(System.out::println) .toArray(String[]::new);` and then compare with `String[] actual = Stream.of(input) .peek(System.out::println) .flatMap(s -> Arrays.stream(s.split(","))) .peek(System.out::println) .toArray(String[]::new);`. It would help you with a confirmation on your own. – Naman Mar 05 '20 at 06:52
  • 1
    Vague title. Rewrite to summarize your specific technical issue. – Basil Bourque Mar 05 '20 at 06:55
  • @Slaw - I updated the question to be more specific by removing the last question. – MasterJoe Mar 05 '20 at 06:57
  • 1
    While it’s correct that the stream processes “one element at a time”, it’s nothing you should worry about. You have defined an operation *for each element*, the order of processing doesn’t matter. – Holger Mar 05 '20 at 08:00

1 Answers1

0

Predefined syntax of flat map is

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

where, R is the element type of the new stream.
Stream is an interface and T is the type 
of stream elements. mapper is a stateless function 
which is applied to each element and the function
returns the new stream.

so how flatMap works internally?

It first applies the function returning another Optional to the object inside (if present) and then flattens the result before returning it, so you don’t have to do it yourself.

internally its defined something like this

public static <T> Optional<T> flatten(Optional<Optional<T>> optional) {
    return optional.orElse(Optional.empty());
}

So in your case

String [] actual = Stream.of(input)
            .flatMap(s -> Arrays.stream(s.split(",")))
            .toArray(String [] :: new);

StreamofInput(input)  - taking input as collection
flatMap: adding map function
s-> Arrays.stream(s.split(","))- taking argument from your arrays individually which is represent by "s" , then converting your array which is splitted by "," and converting into stream.
toArray : converting you result into flat single array because its stateless so it will give you new collection.

for more you can visit here

Negi Rox
  • 3,828
  • 1
  • 11
  • 18