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
JavaScript
x
[
{
"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
JavaScript
[
{
"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
JavaScript
ItemArray.stream().reduce((identity, accumulator) -> {
accumulator.getGenres().forEach((k) -> {});
return identity;
});
Advertisement
Answer
I think it would be easier not to use streams:
JavaScript
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:
JavaScript
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())));