Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 - Filter list inside map value

I am writing a method which takes an input Map of the form Map<Term, List<Integer>> where a Term is defined here.

Method:

  1. Go over the keys of the Map and filter them using a Term attribute.
  2. For each of the remaining keys, get the size of the corresponding list, cap it to 5 (min(List.size(), 5)) and add the output to a global var (say, totalSum)
  3. Return totalSum

This is what I have written so far:

 inputMap
    .entrySet()
    .stream()
    .filter(entry -> entry.getKey().field().equals(fieldName))    // Keep only terms with fieldName
    .forEach(entry -> entry.getValue()
        .map(size -> Math.min(entry.getValue().size(), 5)))   // These 2 lines do not work
        .sum();

I am unable to take as input a stream of lists, output an integer for each of those lists and return the sum of all the outputs.

I can obviously write it using for loops, but I am trying to learn Java 8 and was curious if this problem is solvable using it.

like image 209
vinayakshukl Avatar asked Mar 21 '16 07:03

vinayakshukl


People also ask

Can we use filter and map together in Java 8?

Once we have the Stream of Integer, we can apply maths to find out even numbers. We passed that condition to the filter method. If we needed to filter on String, like select all string which has length > 2 , then we would have called filter before map. That's all about how to use map and filter in Java 8.

How do I filter a map based on values in Java 8?

filter() A more modern way to filter maps would be leveraging the Stream API from Java 8, which makes this process much more readable. The filter() method of the Stream class, as the name suggests, filters any Collection based on a given condition.

How do I filter a map with a stream?

Filter Map Elements using Java Streams Firstly, we created a stream of our Map#Entry instances and used filter() to select only the Entries where person name starts with 'J'. Lastly, we used Collectors#toMap() to collect the filtered entry elements in the form of a new Map.

What is the difference between map and filter in Java 8?

Filter takes a predicate as an argument so basically you are validating your input/collection against a condition, whereas a map allows you to define or use a existing function on the stream eg you can apply String. toUpperCase(...) etc. and transform your inputlist accordingly.


2 Answers

You don't need the forEach method. You can map each entry of the Map to an int, and sum those integers :

int sum = inputMap
    .entrySet()
    .stream()
    .filter(entry -> entry.getKey().field().equals(fieldName))
    .mapToInt(entry -> Math.min(entry.getValue().size(), 5))
    .sum();
like image 123
Eran Avatar answered Sep 28 '22 06:09

Eran


With Eclipse Collections, the following will work using MutableMap and IntList.

MutableMap<Term, IntList> inputMap =
    Maps.mutable.of(term1, IntLists.mutable.of(1, 2, 3), 
                    term2, IntLists.mutable.of(4, 5, 6, 7));

long sum = inputMap
    .select((term, intList) -> term.field().equals(fieldName))
    .sumOfInt(intList -> Math.min(intList.size(), 5));

Note: I am a committer for Eclipse Collections.

like image 28
itohro Avatar answered Sep 28 '22 06:09

itohro