Using Stream to match collection result

I am trying to come up with a way to do this without calling 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());

According to the request:

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

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

Is there a better way to do this?

+4
source share
2 answers

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 does not return a stream. Another solution:

    List<ArtistWithSongs> artistWithSongsList = new ArrayList<>();
    songs.stream()
         .collect(Collectors.groupingBy(Song::getArtist))
         .forEach((artist, songs) -> artistWithSongsList.add(new ArtistWithSongs(artist, songs)););
-1
source

I think when using forEach enough in this case:

List<ArtistWithSongs> artistWithSongsList = new ArrayList<>();
service.getSongs().stream()
                  .collect(Collectors.groupingBy(s -> s.getArtist(), Collectors.toList()))
                  .entrySet()
                  .forEach((k, v) -> artistWithSongsList.add(new ArtistWithSongs(k, v)););
0
source

Source: https://habr.com/ru/post/1668320/


All Articles