3

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?

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
user902383
  • 8,420
  • 8
  • 43
  • 63
  • Can you include some example of input and expected result, which would also let us see sense of `isGroupAccepting(item.getId,groupid)`? Maybe you can change it into something like `static long toWhichGroupItemShouldBelong(Item item){ .. return destinationGroupID;}` which would let you write code like `items.stream().collect(Collectors.groupingBy(YourClass::toWhichGroupItemShouldBelong))`. – Pshemo Apr 10 '19 at 11:52

2 Answers2

6

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())));
Eran
  • 387,369
  • 54
  • 702
  • 768
1

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.

user_3380739
  • 1
  • 14
  • 14