Reputation: 3294
I've two objects in my java project that are something like this:
FavoriteGroup
- int id
- string userId
- string name
- List<Favorite> favorites
and
Favorite
- int id
- int groupId
- string title
- string path
Now, I've a List of items that may repeat the groups. Do I have a way to group that list in a way that for each FavoriteGroup I've all my Favorite list joined?
More graphical explanation: I've:
[{
id: 1,
userId: 1,
name: "Group one",
favorites: [{
id: 100,
groupId: 1,
title: "Favorite 1",
path: "path 1"
}]
},
{
id: 1,
userId: 1,
name: "Group one",
favorites: [{
id: 200,
groupId: 1,
title: "Favorite 2",
path: "path 2"
}]
},
{
id: 2,
userId: 1,
name: "Group two",
favorites: [{
id: 300,
groupId: 2,
title: "Favorite 3",
path: "path 3"
}]
}]
And I need:
[{
id: 1,
userId: 1,
name: "Group one",
favorites: [{
id: 100,
groupId: 1,
title: "Favorite 1",
path: "path 1"
},
{
id: 200,
groupId: 1,
title: "Favorite 2",
path: "path 2"
}]
},
{
id: 2,
userId: 1,
name: "Group two",
favorites: [{
id: 300,
groupId: 2,
title: "Favorite 3",
path: "path 3"
}]
}]
What's the best way to do this? using for loop iterations or maybe grouping java 8 stream functions?
Upvotes: 2
Views: 5803
Reputation: 7907
Try this:-
favoriteGroups.stream()
.collect(Collectors.toMap(FavoriteGroup::getId, Function.identity(), (fg1, fg2) -> {
//This will modify the original object(s). If you don't want that, then you'll have to clone the object and set favorites.
fg1.setFavorites(Stream.concat(fg1.getFavorites().stream(), fg2.getFavorites().stream())
.collect(Collectors.toList()));
return fg1;
}))
.values();
This will return an object of type Collection<FavoriteGroup>
, which you can iterate over. If you want to convert it back to List
, you can do List<FavoriteGroup> list = new ArrayList<>(favoriteGroupsCollection);
.
Upvotes: 0
Reputation: 21124
I would rather do it like so,
private static final String DELIMITER = "-";
Map<String, List<Favorite>> favsByGroup = favGroups.stream()
.collect(Collectors.groupingBy(g -> g.getId() + DELIMITER + g.getUserId() + DELIMITER + g.getName(),
Collectors.flatMapping(fg -> fg.getFavorites().stream(), Collectors.toList())));
List<FavoriteGroup> mergedFavoriteGroups = favsByGroup.entrySet().stream()
.map(e -> new FavoriteGroup(Integer.parseInt(e.getKey().split(DELIMITER)[0]),
e.getKey().split(DELIMITER)[1], e.getKey().split(DELIMITER)[2], e.getValue()))
.collect(Collectors.toList());
First create a map taking the concatenated Id, userId and name properties of FavoriteGroup
as the key and the List
of Favorite
instances as the value. Then for each entry in the map, I'll create a new FavoriteGroup
by decoding the key and passing the values as it is. As a final step collect
the resulting objects to a container.
Upvotes: 2