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

Comments:

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 #

You can replace

flatMap(l -> l.stream())

by

flatMap(Collection::stream)

Posted by Johannes on July 18, 2017 at 02:18 PM CEST #

This is a pain in my ars. Scala esoteric? Man, you really should know, what you are writing about. You don't know Scala? Only for the money in here?

Posted by Roger on October 19, 2017 at 09:14 PM CEST #

Hi Roger,

it is just the name of the Developer instance in this example. Don't take it too seriously,

thank you for your comment!

--adam

Posted by Adam on October 21, 2017 at 06:14 AM CEST #

In my requirements I want developer name concatenated with language.
Something like
esoteric-clojure
esoteric-scala
esoteric-groovy
esoteric-go

Need help

Posted by Dilip on December 28, 2017 at 07:37 AM CET #

how to collect the elments after:
list.stream().flatMap(a -> Stream.of(a.getNumber1(),a.getNumber2()))

Posted by bindiya on April 11, 2018 at 10:56 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
...the last 150 posts
...the last 10 comments
License