using Java 8 How to filter by list and group by based on filter condition and convert to Map with their count

Sushil

I want to convert below for loop to Java 8. But having problem with filtering list of status and grouping into one status and total count. I tried but for each "LIVE", "DRAFT", "TEST" have to loop 3 times and get 3 different maps. Is it possible to get into one loop using Java-8?

Where "LIVE", "DRAFT" and "TEST" are again combination of status from workflowInstance like DRAFT = {"DRAFT_EDIT","DRAFT_SAVE"}. I want to categorize all status into 3 based on this combination defined.

Map<String, Integer> summaryMap = new HashMap<>();
int l = 0, d = 0, t = 0;

for (WorkflowInstance instance : workflowInstances) {
    if (liveStatuses.contains(instance.getStatus())) {
        summaryMap.put("LIVE", l++);
    } else if (testStatuses.contains(instance.getStatus())) {
        summaryMap.put("TEST", t++);
    } else if (draftStatuses.contains(instance.getStatus())) {
        summaryMap.put("DRAFT", d++);
    }
}

Java-8 individually for "LIVE", "DRAFT" and "TEST":

map.put("DRAFT", workflowInstances.stream()
     .filter(inst-> Constants.DRAFT_STATUS.contains(inst.getStatus()))
     .collect(Collectors.groupingBy(WorkflowInstance::getStatus, Collectors.counting()))
     .entrySet().stream().mapToLong(e-> e.getValue()).sum()
);

map.put("LIVE", workflowInstances.stream()
     .filter(inst-> Constants.LIVE_STATUS.contains(inst.getStatus()))
     .collect(Collectors.groupingBy(WorkflowInstance::getStatus, Collectors.counting()))
     .entrySet().stream().mapToLong(e-> e.getValue()).sum()
);

// Similar for "TEST"

Instead of looping 3 times I want to do in 1 go and categorize them. Any help would be appreciated.

Nikolas

You cannot avoid extracting the type of the status anyway. Create a dedicated method for it (I suppose the list of statuses as liveStatuses etc. are either static or instance variables. Note that you have forgotten to handle the case no one of the predefined statuses match the current one. In that case, let's use "UNDEFINED":

String extractStatus(WorkflowInstance workflowInstance) {
    String status = workflowInstance.getStatus();
    if (liveStatuses.contains(status)) {
        return "LIVE";
    } else if (testStatuses.contains(status)) {
        return "TEST";
    } else if (draftStatuses.contains(status)) {
        return "DRAFT";
    }
    return "UNCATEGORIZED";                          // in case nothing is matched
}

Then the collecting is fairly easy using Collectors.groupingBy with a combination of Collectors.counting:

Map<String, Long> map = workflowInstances.stream()
    .collect(Collectors.groupingBy(                  // groups to Map
            this::extractStatus,                     // extracted status is the key
            Collectors.counting()));                 // value is a number of occurences

Note the result is Map<String, Long> if you insist on Map<String, Integer> you need an additional downstream collector using Collectors.collectingAndThen:

Map<String, Integer> map = workflowInstances.stream()
    .collect(Collectors.groupingBy(                   // groups to Map
            Foo::extractStatus,                       // extracted status is the key
            Collectors.collectingAndThen(             // value is collected ...
                    Collectors.counting(),            // ... a number of occurences
                    count -> new BigDecimal(count)    // ... as Integer from Long
                                 .intValueExact()))); // ... but might throw an exception 

Using The ArithmeticException is thrown if the number is outside bounds. Remember that Long has the way bigger range than Integer. There are many different ways of the conversion of Long->Integer but they follow the same principle.

... or use a simple trick using Collectors.summingInt(e -> 1) instead of Collectors.counting as @HadiJ suggested. It returns Integer instead:

Map<String, Integer> map = workflowInstances.stream()
    .collect(Collectors.groupingBy(this::extractStatus, Collectors.summingInt(e -> 1)));

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

using Java 8 How to filter by list and group by based on filter condition and convert to Map with their count

From Dev

How to filter Map by a List using Java 8 stream?

From Dev

Java 8 Filter list based on condition from the part of the list

From Dev

Java 8 Applying stream filter based on a condition

From Dev

Java8 : How to filter a map of List value via stream

From Dev

Using Streams filter Map based on a list of keys

From Dev

Java 8 - Filter list inside map value

From Dev

Java 8 lambda returning an empty list of map keys based on a filter applied to map objects

From Dev

How to filter a List using Java 8 stream and startwith array of values

From Java

How to filter map of map using java stream

From Dev

How to filter map of map using java stream

From Dev

How to filter a map by its values in Java 8?

From Dev

Skip Java Filter based on Condition

From Dev

Skip Java Filter based on Condition

From Dev

How to convert List to Map with indexes using stream - Java 8?

From Dev

How to do filter a list in Java8?

From Dev

How to group by and count based on a condition

From Dev

Convert List to map using java 8

From Dev

how to filter a JavaRDD using a List using java

From Dev

Filter data based on result set of group and count

From Dev

Java 8 map filter and sort

From Dev

filter Map in Java 8 Streams

From Dev

Java 8 filter based on a boolean

From Dev

Java 8: Iterate over a list and add to a map based on condition

From Dev

How to convert Map to List in Java 8

From Dev

How to match objects from list with data from map with condition and save to another map using Java 8 Streams

From Dev

Filter on a value of inner Map using Java 8 streams

From Dev

How to using stream in java 8 filter two list object and set value to new List

From Dev

How to use java 8 streams to make a new list by using another's list objects values with filter?

Related Related

  1. 1

    using Java 8 How to filter by list and group by based on filter condition and convert to Map with their count

  2. 2

    How to filter Map by a List using Java 8 stream?

  3. 3

    Java 8 Filter list based on condition from the part of the list

  4. 4

    Java 8 Applying stream filter based on a condition

  5. 5

    Java8 : How to filter a map of List value via stream

  6. 6

    Using Streams filter Map based on a list of keys

  7. 7

    Java 8 - Filter list inside map value

  8. 8

    Java 8 lambda returning an empty list of map keys based on a filter applied to map objects

  9. 9

    How to filter a List using Java 8 stream and startwith array of values

  10. 10

    How to filter map of map using java stream

  11. 11

    How to filter map of map using java stream

  12. 12

    How to filter a map by its values in Java 8?

  13. 13

    Skip Java Filter based on Condition

  14. 14

    Skip Java Filter based on Condition

  15. 15

    How to convert List to Map with indexes using stream - Java 8?

  16. 16

    How to do filter a list in Java8?

  17. 17

    How to group by and count based on a condition

  18. 18

    Convert List to map using java 8

  19. 19

    how to filter a JavaRDD using a List using java

  20. 20

    Filter data based on result set of group and count

  21. 21

    Java 8 map filter and sort

  22. 22

    filter Map in Java 8 Streams

  23. 23

    Java 8 filter based on a boolean

  24. 24

    Java 8: Iterate over a list and add to a map based on condition

  25. 25

    How to convert Map to List in Java 8

  26. 26

    How to match objects from list with data from map with condition and save to another map using Java 8 Streams

  27. 27

    Filter on a value of inner Map using Java 8 streams

  28. 28

    How to using stream in java 8 filter two list object and set value to new List

  29. 29

    How to use java 8 streams to make a new list by using another's list objects values with filter?

HotTag

Archive