Java 8 grouping by from one-to-many
I think you are after Collectors.mapping which can be passed as a second argument to groupingBy
Complete example
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);
}
}
In case someone looking for a working example, the below should be useful.
import java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class GroupSubject {
public static void main(String[] args) {
List<ContentItem> items = Arrays.asList(new ContentItem("maths"), new ContentItem("science"),
new ContentItem("social"), new ContentItem("chemistry"), new ContentItem("maths"));
Map<String, List<ContentItem>> x = (Map<String, List<ContentItem>>) items.stream()
.flatMap(item -> item.getSubjects().stream().map(subject -> pair(subject, item)))
.collect(Collectors.groupingBy(e -> ((SimpleEntry<String, ContentItem>) e).getKey(), Collectors
.mapping(e -> ((SimpleEntry<String, ContentItem>) e).getValue(), Collectors.toList())));
System.out.println(x);
}
private static <T, U> AbstractMap.SimpleEntry<T, U> pair(T t, U u) {
return new AbstractMap.SimpleEntry<T, U>(t, u);
}
}
class ContentItem {
private List<String> subjects = new ArrayList<String>();
public ContentItem(String string) {
subjects.add(string);
}
public List<String> getSubjects() {
return subjects;
}
public void setSubjects(List<String> subjects) {
this.subjects = subjects;
}
}