Reputation: 1081
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
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
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
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
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