Java 8 Streams Flatmap Method Example

Java 8 Streams FlatMap method example

It doesn't make sense to flatMap a Stream that's already flat, like the Stream<Integer> you've shown in your question.

However, if you had a Stream<List<Integer>> then it would make sense and you could do this:

Stream<List<Integer>> integerListStream = Stream.of(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5)
);

Stream<Integer> integerStream = integerListStream .flatMap(Collection::stream);
integerStream.forEach(System.out::println);

Which would print:

1
2
3
4
5

To do this pre-Java 8 you just need a loops:

List<List<Integer>> integerLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5)
)

List<Integer> flattened = new ArrayList<>();

for (List<Integer> integerList : integerLists) {
flattened.addAll(integerList);
}

for (Integer i : flattened) {
System.out.println(i);
}

What's the difference between map() and flatMap() methods in Java 8?

Both map and flatMap can be applied to a Stream<T> and they both return a Stream<R>. The difference is that the map operation produces one output value for each input value, whereas the flatMap operation produces an arbitrary number (zero or more) values for each input value.

This is reflected in the arguments to each operation.

The map operation takes a Function, which is called for each value in the input stream and produces one result value, which is sent to the output stream.

The flatMap operation takes a function that conceptually wants to consume one value and produce an arbitrary number of values. However, in Java, it's cumbersome for a method to return an arbitrary number of values, since methods can return only zero or one value. One could imagine an API where the mapper function for flatMap takes a value and returns an array or a List of values, which are then sent to the output. Given that this is the streams library, a particularly apt way to represent an arbitrary number of return values is for the mapper function itself to return a stream! The values from the stream returned by the mapper are drained from the stream and are passed to the output stream. The "clumps" of values returned by each call to the mapper function are not distinguished at all in the output stream, thus the output is said to have been "flattened."

Typical use is for the mapper function of flatMap to return Stream.empty() if it wants to send zero values, or something like Stream.of(a, b, c) if it wants to return several values. But of course any stream can be returned.

flatMap triple nested streams

You can do this in two steps:

first create concatenation of countries and titles list:

List<String> countriesTitle = countries.stream()
.flatMap(country -> titles.stream()
.map(title -> country + "_" + title))
.collect(Collectors.toList());

then by previous result create list of concatenation country+"_"+title+"_"+game string:

Stream.concat(games.stream(),
games.stream()
.flatMap(game -> countriesTitle.stream()
.map(countryTitle -> countryTitle + "_" + game)))
.collect(Collectors.toList());

Updated answer:

games.stream()
.flatMap(game -> countries.stream()
.flatMap(country -> titles.stream()
.flatMap(title -> Stream.of(game, country + "_" + title + "_" + game))))
.collect(Collectors.toSet());

Java 8: Flattening StreamStream

flatMap( i -> i) will essentially concatenate the streams.

Usage of flatMap() in Java8

Your external loop counts the number of members that have the band coming from Kolkata. if you actually want that:

long result = artists.stream().filter(a -> a.getOrigin().equals("Kolkata"))
.filter(a -> a.getMembers() != null)
.flatMap(a -> a.getMembers())
.count();

Using Java 8's Optional with Stream::flatMap

Java 9

Optional.stream has been added to JDK 9. This enables you to do the following, without the need of any helper method:

Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();

Java 8

Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional<T> into a zero-or-one length Stream<T>. You could do this:

Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();

Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:

/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}

Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();

Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.

Nested lists with streams in Java8

You can use two flatMap then a filter then you can pick the first one or if no result return null :

C c1 = listOfAObjects.stream()
.flatMap(a -> a.getList().stream())
.flatMap(b -> b.getPr().stream())
.filter(c -> c.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);

How can I turn a List of Lists into a List in Java 8?

You can use flatMap to flatten the internal lists (after converting them to Streams) into a single Stream, and then collect the result into a list:

List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());


Related Topics



Leave a reply



Submit