Home > OS >  Use groupingBy and filtering out entire groups
Use groupingBy and filtering out entire groups

Time:09-23

I have a list of MyObjects like this

ID Type Description
1 Summary
1 Detail keep this group
1 Detail keep this group
2 Summary
2 Detail don't keep this group
2 Detail don't keep this group

I'd like to group the list by ID and filter out the groups that do not contain any Descriptions with "keep this group" as the value.

Below is what I have tried

   Map<String, List<MyObject>> output =
        myObjectList.stream()
            .collect(Collectors.groupingBy(MyObject::getId,
                    Collectors.filtering(x -> x.getDescription().equals("keep this group"),
                        Collectors.toList())));

This does not really work thought. It creates the groups and removes all elements without "keep this group"

So group 1 has 2 elements and group 2 has 0 elements

I'd like to completely reject group 2 and keep all elements in group 1

CodePudding user response:

I have not tested code. It will remove group which does not have any object description equals "keep this group".

Map<String, List<MyObject>> output =
 myObjectList.stream() 
.collect(Collectors.groupingBy(MyObject::getId))
.entrySet()
.stream()
.filter(e-> e.getValue().stream().filter(o->o.getDescription().equals("keep this group")).count()>0)
.collect(Colletors.toMap(Map.Entry::getKey, Map.Entry::getValue));

CodePudding user response:

It seems that Collectors.collectingAndThen should be used to filter out the groups where there is no any item in the value list:

Map<String, List<MyObject>> output = myObjectList
    .stream()
    .collect(Collectors.collectingAndThen(
        Collectors.groupingBy(MyObject::getId), // Map<String, List<MyObject>>
        map -> { 
            map.entrySet().removeIf(
                e -> e.getValue()
                      .stream()
                      .noneMatch(obj -> "keep this group".equals(obj.getDescription()))
            );
            return map;
        }
    ));
  • Related