Dusan Vasiljevic Dusan Vasiljevic - 4 years ago 98
Java Question

Using Stream to map Collection result

I'm trying to think of a way to do this without invoking

stream()
twice but to no avail:

List<Song> songs = service.getSongs();

List<ArtistWithSongs> artistWithSongsList = songs.stream()
.collect(Collectors
.groupingBy(s -> s.getArtist(), Collectors.toList()))
.entrySet()
.stream()
.map(as -> new ArtistWithSongs(as.getKey(), as.getValue()))
.collect(Collectors.toList());


As requested:

class ArtistWithSongs {
private Artist artist;
private List<Song> songs;

ArtistWithSongs(Artist artist, List<Song> songs) {
this.artist = artist;
this.songs = songs;
}
}


Is there a more optimal way of doing this?

Answer Source

I think you can use FlatMap:

List<Song> songs = service.getSongs();

List<ArtistWithSongs> artistWithSongsList = songs.stream()
               .collect(Collectors
               .groupingBy(s -> s.getArtist(), Collectors.toList()))
               .entrySet()
               .flatMap(as -> new ArtistWithSongs(as.getKey(), as.getValue()))
               .collect(Collectors.toList());

Edit:

Sorry we cannot use flatMap after collect() because it doesnot return stream. Other solution is:

    List<ArtistWithSongs> artistWithSongsList = new ArrayList<>();
    songs.stream()
         .collect(Collectors.groupingBy(Song::getArtist))
         .forEach((artist, songs) -> artistWithSongsList.add(new ArtistWithSongs(artist, songs)););
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download