Prpaa Prpaa - 1 month ago 10
Java Question

Java stream Map by value which is Collection

How to stream a

Map
which looks like
Map<String, <List<String>>

to get:


  1. List<String>
    from a map.getValue() which for ex. are all longer than 5 or map.getValue() each string which str.length()>5.
    How to get long count of these?

  2. Map<String, List<String>>
    where keys stay the same, but the list consists only of
    String
    s of length larger than 5?

  3. Map<String, long>
    with counts of strings larger than five in List per maps key?



I started something but I am stuck:

long l = map.entrySet().stream()
.filter(m -> m.getValue().stream().filter(s -> s.length() > 5)


Thanks

Answer

It looks like you want to create a new Map from the source Map, where the keys remain the same and the values are filtered :

Sample input :

Map<String, List<String>> map = new HashMap<> ();
map.put ("one", Arrays.asList (new String[]{"1","2","12345","123456"}));
map.put ("two", Arrays.asList (new String[]{"1","123456","12345","12"}));
map.put ("three", Arrays.asList (new String[]{"1","2","12","34"}));
map.put ("four", Arrays.asList (new String[]{"12345","123456","1234567","123"}));

Processing :

Map<String, List<String>> output =
    map.entrySet()
       .stream()
       .collect(Collectors.toMap(Map.Entry::getKey,
                                 e->e.getValue()
                                     .stream()
                                     .filter(s -> s.length() > 5)
                                     .collect(Collectors.toList())));

Output :

{four=[123456, 1234567], one=[123456], three=[], two=[123456]}

EDIT :

After re-reading your question, it looks like you asked three different questions and I only answered the second of them.

The third is a small variation of the second :

Map<String, Long> output =
    map.entrySet()
       .stream()
       .collect(Collectors.toMap(Map.Entry::getKey,
                                 e->e.getValue()
                                     .stream()
                                     .filter(s -> s.length() > 5)
                                     .count()));

EDIT :

As for the first question, you can merge the Lists using flatMap and then filter out the short Strings :

List<String> longStrings = 
    map.values()
       .stream()
       .flatMap(Collection::stream)
       .filter(s->s.length() > 5)
       .collect(Collectors.toList());
Comments