Java 8 FlatMap Example
A developer knows a set of programming languages:
public class Developer {
private String name;
private Set<String> languages;
public Developer(String name) {
this.languages = new HashSet<>();
this.name = name;
}
public void add(String language) {
this.languages.add(language);
}
public Set<String> getLanguages() {
return languages;
}
}
A team has more than one developers. Now we would like to know the aggregate programming language skills for a given team.
Stream#flatMap is
perfect for "flattening" collections:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class FlatMapTest {
@Test
public void flatMap() {
List<Developer> team = new ArrayList<>();
Developer polyglot = new Developer("esoteric");
polyglot.add("clojure");
polyglot.add("scala");
polyglot.add("groovy");
polyglot.add("go");
Developer busy = new Developer("pragmatic");
busy.add("java");
busy.add("javascript");
team.add(polyglot);
team.add(busy);
List<String> teamLanguages = team.stream().
map(d -> d.getLanguages()).
flatMap(l -> l.stream()).
collect(Collectors.toList());
assertTrue(teamLanguages.containsAll(polyglot.getLanguages()));
assertTrue(teamLanguages.containsAll(busy.getLanguages()));
}
}
Related: Java 8 CompletableFuture Example
See you at Java EE Workshops at Munich Airport, Terminal 2, particularly at: Java 8 with Java EE 7 or Virtual Dedicated Workshops / consulting
NEW workshop: HTML 5 and JavaScript Essentials, Three days in April 2017: from Java EE 7 Architectures over Microservices to Performance, Troubleshooting and Monitoring
On demand workshops: Java EE 7: Bootstrap, Effective, Testing and Microservices available for streaming.
Newsletter: airhacks.news

If you happen to have Guava, which people at my current work place love very much, in your project and don't use Java 8, you can use:
Iterables.concat(
Iterables.transform(
team,
new Function<Developer, Set<String>>() {
public Set<String> apply(Developer d) {
return d.getLanguages();
}
}
)
);
Posted by Thai on December 26, 2014 at 09:39 AM CET #
Thanks for the post, but what about just:
team.stream().flatMap(d -> d.getLanguages().stream()).collect(Collectors.toList());
... I faced a similar problem some days ago and yes, flatMap is useful!
Posted by chpjava8 on December 26, 2014 at 11:01 AM CET #
Thanks for sharing this post !!
Posted by Subham on December 29, 2014 at 02:48 AM CET #
I would expect teamLanguages to be a set rather than a list; could you use Collectors.toSet instead of Collectors.toList? - or is there some pitfall in that approach?
Posted by pedrow on December 29, 2014 at 05:39 PM CET #
I agree with Subham, Set is a better choice because we are only interested in languages, no duplicates. Collectiors.toSet() should be used.
Posted by Javin on January 21, 2015 at 04:33 PM CET #
Suppose you create the List of Developer, using the Stream API, from a text file. The lines contain: developer name, language. Would you use flatMap using String as input and Stream.of Developer as output on a change of developer name? Or would you use a reduce or collect/Consumer?
Also, if a flatMap is used, how to know when the input stream stops and flushing out the last Developer?
Posted by Rene on June 04, 2015 at 04:46 PM CEST #
This would be way more useful for people grappling with flatmap if you explained what the flatmap was doing. I.e. put some explanation around
flatMap(l -> l.stream())
Posted by mark on October 20, 2015 at 12:43 PM CEST #
Adam, could you have a post about CompletableFuture?
Posted by Thai on February 10, 2016 at 07:47 PM CET #
Hi,
I tried with flatMap(l -> Stream.of(l)) and I could not get it as one single list . Can you explain whats the difference between flatMap(l -> l.stream()) and flatMap(l->Stream.of(l)). Thanks.
Posted by puspa on April 24, 2016 at 01:44 PM CEST #
I am leaning these concepts and in your example would it be the same to write:
teamLanguages = team.stream().
map(d -> d.getLanguages()).
flatMap(l -> l.stream()).
collect(Collectors.toList());
to this:
teamLanguages = team.stream().flatMap(d -> d.getLanguages()).collect(Collectors.toList());
???
Posted by Christian on May 05, 2016 at 11:14 PM CEST #
You can write as the following:
List<String> teamLanguages = team.stream().flatMap(d -> d.getLanguages().stream()).collect(Collectors.toList());
Posted by Tu on July 01, 2016 at 05:18 AM CEST #
What do you think about a possible Scala version of the above example?
case class Developer(name: String, languages: Set[String])
List(
Developer("esoteric", Set("clojure", "scala", "groovy", "go")),
Developer("pragmatic", Set("java", "javascript"))
).
flatMap(_.languages)
Posted by János Setény on August 29, 2016 at 10:17 AM CEST #
I just love your blog. I am trying to learn these concepts from you. It's easy to learn because there are lots of videos. Thanks for sharing. I hope we can get more and more lessons and helps me to be a professional programmer.
Posted by Jeniffer Lenirs on September 17, 2016 at 08:21 PM CEST #
Hi Thai,
your CompletableFuture example request: http://www.adam-bien.com/roller/abien/entry/java_8_completablefuture_example
:-)
enjoy Java (EE),
--adam
Posted by adam bien on October 07, 2016 at 03:38 AM CEST #
Thanks for sharing this Code
Posted by Muhammad iqbal on October 27, 2016 at 02:41 PM CEST #
It would be useful if there was some explanation of what is actually happening. Also, the 'l' in the flatMap part looks like a '1' :)
Posted by John D on October 30, 2016 at 05:03 PM CET #