Home > Enterprise >  Java Streams Map, Get Value - List<Integer> from Key (With filtering)
Java Streams Map, Get Value - List<Integer> from Key (With filtering)

Time:11-02

Assuming I'm writing a method that takes in Map<String, List<Integer>> as shown below, and a String name to filter. My return type is Stream<Integer> how do I convert from a Stream<List<Integer>> to Stream<Integer>?

Map<String, List<Integer>> person = Map.of("John", List.of(54, 18), 
                                           "Alex",  List.of(28), 
                                           "Tom", List.of(78, 42));

My current implementation returns a Stream<List<Integer>>. Realistically, I would iterate through the list to retrieve all Integers in the list.

Code implementation:

return table.entrySet().stream()
  .filter(map -> map.getKey().equals(name))
  .map(map -> map.getValue());

CodePudding user response:

As @Thomas has pointed out in the comments, iterating over the whole Map would be wasteful. And solution he proposed probably is the cleanest one:

map.getOrDefault(name, Collections.emptyList()).stream()

Alternatively, you can make use of flatMap() without performing redundant iteration through the whole map like that:

public static <K, V> Stream<V> getStreamByKey(Map<K, Collection<V>> map,
                                              K key) {

    return Stream.ofNullable(map.get(key))
        .flatMap(Collection::stream);
}

The same result can be achieved with Java 16 mapMulti():

public static <K, V> Stream<V> getStreamByKey(Map<K, Collection<V>> map,
                                              K key) {
    
    return Stream.ofNullable(map.get(key))
        .mapMulti(Iterable::forEach);
}

CodePudding user response:

As others pointed out in comments, use flatMap instead of map in the last step to reduce the double nesting:

return table.entrySet().stream()
    .filter(map -> map.getKey().equals(name))
    .flatMap(entry -> entry.getValue().stream());
  • Related