Adam Bien's Weblog

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

A book about rethinking Java EE Patterns

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 #

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