I have a movie list from a web service that i need to group using genres attribute from the data. My question is very similar to this groupby ngFor angular2 but in java instead.
movie list from the web service looks like this
[
{
"title": "AAAAAAAA",
"genres": [
"Comedy"
]
},
{
"title": "BBBBBBBBBBBB",
"genres": [
"Action", "Adventure"
]
},
{
"title": "CCCCCCCCCCCCC",
"genres": [
"Action"
]
},
{
"title": "DDDDDDDDDDDD",
"genres": [
"Comedy", "Adventure"
]
},
{
"title": "EEEEEEEEEEEEEEEEEEE",
"genres": [
"Horror"
]
}
]
here is what i'm trying to achieve but i cant seems to get it right
[
{
"Action": [
{
"title": "BBBBBBBBBBBB",
"genres": [
"Action", "Adventure"
]
},
{
"title": "CCCCCCCCCCCCC",
"genres": [
"Action"
]
}
],
"Adventure": [
{
"title": "BBBBBBBBBBBB",
"genres": [
"Action", "Adventure"
]
},
{
"title": "DDDDDDDDDDDD",
"genres": [
"Comedy", "Adventure"
]
}
],
"Comedy": [
{
"title": "AAAAAAAA",
"genres": [
"Comedy"
]
},
{
"title": "DDDDDDDDDDDD",
"genres": [
"Comedy", "Adventure"
]
}
],
"Horror": [
{
"title": "EEEEEEEEEEEEEEEEEEE",
"genres": [
"Horror"
]
}
]
}
]
i've tried replicating the javascript solution from the answer in groupby ngFor angular2 but I'm stucked
ItemArray.stream().reduce((identity, accumulator) -> {
accumulator.getGenres().forEach((k) -> {});
return identity;
});
CodePudding user response:
I think it would be easier not to use streams:
Map<String, List<Item>> itemsByGenre = new HashMap<>();
for (Item item : items) {
for (String genre : item.genres()) {
itemsByGenre.computeIfAbsent(genre, g -> new ArrayList<>()).add(item);
}
}
The key point here is that you need to explode by genre, because each item can be in multiple genres. So, you could do something like this:
Map<String, List<Item>> itemsByGentre = items.stream()
// Make a stream of map entries where the key is the genre, and the value is the item.
.flatMap(i -> i.genres().stream().map(g -> new AbstractMap.SimpleEntry<>(g, i))
.collect(
// Now, group by key (genre)...
Collectors.groupingBy(
Map.Entry::getKey,
// and map the entry to just the value (the item),
// and collect the items into a list.
Collectors.mapping(Map.Entry::getValue, Collectors.toList())));