Soumya Kanti Naskar
Soumya Kanti Naskar

Reputation: 1081

Usage of flatMap() in Java8

I have an Artist class as follows:

class Artist {
    private final String name;
    private final String origin;
    private Stream<Artist> members;

    public Artist(String name, String origin) {
        this.name = name;
        this.origin = origin;
        this.members = null;
    }

    public Artist(String name, String origin,Stream<Artist> members) {
            this.name = name;
            this.origin = origin;
            this.members = members;
    }

    public String getName() {
            return name;
    }

    public String getOrigin() {
        return origin;
    }

    public Stream<Artist> getMembers() {
        return members;
    }

    @Override
    public String toString() {
        return name;
    }
}

Now we create a list of artists, where the name of the artist is a band or a single entity. For single entity "members"attribute remains null.Now the list is as follows :

List<Artist> artists = Arrays.asList(
                new Artist("Fossils","Kolkata", Stream.of(new Artist("Rupam Islam","Kolkata"), new Artist("Deep","Kolkata"),new Artist("Allan","Kolkata"), new Artist("Chandramouli","Kolkata"),new Artist("Tanmoy","Kolkata"))),
                new Artist("Linkin Park","California",Stream.of(new Artist("Chester Bennington","California"),new Artist("Dave Farrell","California"), new Artist("Mike Shinoda","California"),new Artist("Rob Bourdon","California"),new Artist("Brad Delson","California"))),
                new Artist("Cactus","Kolkata",Stream.of(new Artist("Sidhartha Sankar","Kolkata"),new Artist("Dibyendu Mukherjee","Kolkata"), new Artist("Ritaprabha","Kolkata"),new Artist("Sudipto","Kolkata"),new Artist("Mainak","Kolkata"))),
                new Artist("Backstreet Boys","Florida",Stream.of(new Artist("A. J. McLean","Florida"),new Artist("Howie D.","Florida"),new Artist("Nick Carter","Florida"), new Artist("Kevin Richardson","Florida"), new Artist("Brian Littrell","Florida"))),
                new Artist("Prohori","Kolkata",Stream.of(new Artist("Pritam","Kolkata"))));

We want to have no of single entity from "Kolkata". Using external iteration we can have following solution:

int totalMembers = 0;
for (Artist artist : artists) {
    if(artist.getOrigin().equals("Kolkata") {
        Stream<Artist> members = artist.getMembers();
        totalMembers += members.count();
    }
} 

What will be the solution for internal iteration using stream() and flatMap() with the help of Lambda-Expression ?

I have thought of a solution but may be it is incorrect.

int totalMember = artists.stream()
                         .filter(d -> d.getOrigin().equals("Kolkata"))
                         .flatMap(e -> e.getMembers())
                         .map(f -> 1).reduce(0, (a, b) -> a + b);

Upvotes: 2

Views: 2932

Answers (4)

Bohemian
Bohemian

Reputation: 425448

Sum the counts of the streams in an LongStream:

long totalMember = artists.stream()
                          .filter(d -> d.getOrigin().equals("Kolkata"))
                          .map(Artist::getMembers)
                          .filter(m -> m != null)
                          .mapToInt(Stream::count)
                          .sum();

Upvotes: 0

Nisarg Patil
Nisarg Patil

Reputation: 1649

Your solution will give the expected output i.e 11. You also can use :

int totalMembers = (int) artists.stream()
                                .flatMap(d->d.getMembers())
                                .filter(d->d.getOrigin().equals("Kolkata"))
                                .count();

Difference between both the solutions is I have flattened the list before filtering it and used long count(); instead of reduce(). What later solution does is, it checks the origin from Stream<Artist> members and not the origin of artists. Hope this help. I would appreciate if someone can discuss the optimized solution.

Upvotes: 1

Soumya Kanti Naskar
Soumya Kanti Naskar

Reputation: 1081

Check this solution too. It may also happen that a band member form a band of particular locality may not be from the same locality. So the exact solution will be :

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

Upvotes: 0

Eugene
Eugene

Reputation: 121088

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();

Upvotes: 3

Related Questions