问题描述
我想学习如何将Java 8语法与流一起使用并且有点卡住。
I want to learn how to use the Java 8 syntax with streams and got a bit stuck.
当你为每个值都有一个键时,分组很容易。但是如果我为每个值都有一个键列表并且仍然想用groupingBy对它们进行分类呢?我是否必须将其分解为多个语句,或者是否可能有一些流魔术可以使其更简单。
It's easy enough to groupingBy when you have one key for every value. But what if I have a List of keys for every value and still want to categorise them with groupingBy? Do I have to break it into several statements or is there possibly a little stream magic that can be done to make it simpler.
这是基本代码:
List<Album> albums = new ArrayList<>();
Map<Artist, List<Album>> map = albums.stream().collect(Collectors.groupingBy(this::getArtist));
如果每张专辑只有一个艺术家,那就太棒了。但我必须返回一个列表,因为专辑可以有很多艺术家。相册和艺术家当然是用来说明的,我有真实世界的类型..
It works great if there is only one Artist for every Album. But I must return a List since an Album can have many Artists. Album and Artist are used for illustration of course, I have real-world types..
这可能是一个简单的解决方案,但我有一段时间没找到它所以我我呼吁这个网站代表的集体大脑来解决它。 :)如果不存在简单的解决方案,也欢迎使用复杂的解决方案。
There's probably a simple solution but I haven't found it in a while so I'm calling on the collective brain this site represents to solve it. :) A complex solution is also welcome in case a simple one doesn't exist.
在Album类中或作为以Album作为参数的实用程序方法:
In Album class or as an utility method taking an Album as argument:
Artist getArtist(); // ok
List<Artist> getArtist(); // Not ok, since we now have many "keys" for every Album
干杯,
Mikael Grev
Cheers,Mikael Grev
推荐答案
我认为你是在追踪Collectors.mapping,它可以作为第二个参数传递给groupingBy
I think you are after Collectors.mapping which can be passed as a second argument to 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);
}
}
这篇关于Java 8按一对多分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!