Reputation: 231
I'm trying to understand flatMap
: flatMap(x->stream.of(x) )
does not flat the stream and flatMap(x->x.stream())
works and gives the desired result.
Can someone explain the difference between two?
import java.util.*;
import java.util.stream.*;
class TestFlatMap{
public static void main(String args[]){
List<String> l1 = Arrays.asList("a","b");
List<String> l2 = Arrays.asList("c","d");
Stream.of(l1, l2).flatMap((x)->Stream.of(x)).forEach((x)->System.out.println(x));
Stream.of(l1, l2).flatMap((x)->x.stream()).forEach((x)->System.out.println(x));
}
}
Output :
[a, b]
[c, d]
a
b
c
d
Upvotes: 4
Views: 460
Reputation: 220762
The thing you had in mind was this:
Stream.of(l1, l2)
// String[]::new isn't really needed in this simple example,
// but would be in a more complex one...
.flatMap((x)->Stream.of(x.toArray(String[]::new)))
.forEach((x)->System.out.println(x));
Which would also yield a flattened stream of a, b, c, d
as you expected. Stream.of()
comes in two flavours:
Stream.of(T)
taking a single value as explained also by EranStream.of(T...)
taking an array (not a List
as you expected)Since, when passing a List
to Stream.of()
, the only applicable overload is the one taking a single value, you got a Stream<List<String>>
rather than the expected Stream<String>
Upvotes: 5
Reputation: 393771
Stream.of(x)
produces a Stream of a single element - x
. Therefore, flatMap
returns a Stream<List<String>>
instead of Stream<String>
.
On the other hand, x.stream()
where x
is a Collection<E>
returns a Stream<E>
whose source are the elements of the Collection
, so in your case it returns a Stream<String>
, which allows flatMap
to produce a Stream<String>
containing all the String
s in all the List<String>
s of the source Stream
.
You can see that in the Javadoc:
<T> Stream<T> java.util.stream.Stream.of(T t)
Returns a sequential Stream containing a single element.
vs.
Stream<E> stream()
Returns a sequential Stream with this collection as its source.
Upvotes: 7