问题
I'm reviewing some old code, where I'm grouping elements. It looks more or less like this:
Map<Long,List<Items>> groupedItems = ...
for (long groupid : groups){
for (Item item :items){
if (isGroupAccepting(item.getId(),groupid) || groupid == item.getGroup()) {
groupedItems.get(groupid).add(item);
}
}
}
I planned to replace it using grouping from stream API, but I'm stuck. It works fine for my second condition, but how to deal with the first one, where item should be added to every group which accepts that kind of item? Is it actually possible, or am I fighting a lost cause here?
回答1:
You can create pairs of all the valid group IDs and Items, and then group them by group ID:
Map<Long,List<Item>> groupedItems =
groups.stream()
.flatMap(g -> items.stream()
.filter(i -> isGroupAccepting(i.getId(),g) || g == i.getGroup())
.map(i -> new SimpleEnty<>(g,i))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
回答2:
Try Collectors.flatMapping
if you're using Idk 9 or above:
// import static java.util.stream.Collectors.*;
Map<Long, List<Item>> groupedItems = groups.stream()
.collect(groupingBy(Function.identity(),
flatMapping(
groupId -> items.stream()
.filter(item -> isGroupAccepting(item.getId(), groupId) || groupId == item.getGroup()),
toList())));
Not sure why you want to try replace for
loop with lambdas/Stream APIs. To me the for
code looks great. Most time, the lambdas code looks ugly and more difficult to understand.
来源:https://stackoverflow.com/questions/55611546/single-element-in-multiple-groups-when-grouping-with-stream-api