Java 8按一对多分组

Mik*_*rev 9 java grouping mapreduce java-8 java-stream

我想学习如何使用Java 8语法与流,并有点卡住.

当你为每个值都有一个键时,很容易分组.但是如果我为每个值都有一个键列表并且仍然想用groupingBy对它们进行分类呢?我是否必须将其分解为多个语句,或者可能有一些流魔术可以使其更简单.

这是基本代码:

List<Album> albums = new ArrayList<>();
Map<Artist, List<Album>> map = albums.stream().collect(Collectors.groupingBy(this::getArtist));
Run Code Online (Sandbox Code Playgroud)

如果每个专辑只有一个艺术家,那么效果很好.但我必须返回一个列表,因为专辑可以有很多艺术家.专辑和艺术家当然用于说明,我有真实世界的类型..

可能有一个简单的解决方案,但我有一段时间没有找到它,所以我呼吁这个网站代表的集体大脑来解决它.:)如果不存在简单的解决方案,也欢迎使用复杂的解决方案.

在Album类中或作为以Album作为参数的实用程序方法:

Artist getArtist(); // ok

List<Artist> getArtist(); // Not ok, since we now have many "keys" for every Album
Run Code Online (Sandbox Code Playgroud)

干杯,Mikael Grev

小智 15

我想你是在追踪Collectors.mapping,它可以作为第二个参数传递给groupingBy

完整的例子

import java.util.AbstractMap;
import java.util.List;
import java.util.Map;

import static java.util.Arrays.asList;
import static java.util.Map.Entry;
import static java.util.stream.Collectors.*;

public class SO {

    public static void main(String... args) {

        List<Album> albums = asList(
                new Album(
                        asList(
                                new Artist("bob"),
                                new Artist("tom")
                        )
                ),
                new Album(asList(new Artist("bill")))
        );

        Map<Artist, List<Album>> x = albums.stream()
                .flatMap(album -> album.getArtist().stream().map(artist -> pair(artist, album)))
                .collect(groupingBy(Entry::getKey, mapping(Entry::getValue, toList())));

        x.entrySet().stream().forEach(System.out::println);
    }

    static class Artist {
        private final String name;

        Artist(String name) {
            this.name = name;
        }

        public String toString() {return name;}

    }

    static class Album {
        private List<Artist> artist;

        Album(List<Artist> artist) {
            this.artist = artist;
        }

        List<Artist> getArtist() {
            return artist;
        }

    }

    private static <T,U> AbstractMap.SimpleEntry<T,U> pair(T t, U u) {
        return new AbstractMap.SimpleEntry<T,U>(t,u);
    }


}
Run Code Online (Sandbox Code Playgroud)