How to stream a map with collection using Java 8 streams?

孤街浪徒 提交于 2019-12-06 16:29:30

问题


I'd like to stream a map with collection using Java 8 streams.

For example, having the following data:

Map<String, Collection<Integer>> data;

I'd like to go over the elements handling each integer value with the corresponding key strings. For example:

data.keyValueStream((k,v)-> ...)

Any idea how to achieve this? Thanks.

* Regarding the question "Why do you need it?", it could be a bunch of reasons and I'm not sure it's important. Anyhow, I'll "flow" with you... My specific scenario is to batch insert into a DB all the values, under their specific key. Let's keep it a general Java 8 stream question...


回答1:


You can map your Map<String, Collection<Integer>> to List<Map.Entry<String, Integer>>:

data.entrySet().stream()
  .flatMap(e -> e.getValue().stream().map(v -> new HashMap.SimpleEntry<>(e.getKey(), v)))
  .forEach(e -> System.out.printf("key %s val %d%n", e.getKey(), e.getValue()));

or:

data.forEach((k, v) -> v.forEach(n -> System.out.printf("key %s val %d%n", k, n)));



回答2:


I realize that you ware asking about stream version, but if you are NOT going to use parallelism simplest and probably more efficient option would be using nested loops. This way you can avoid spending time and space on creating temporary instances for each <Key,CollectionItem> pair.

Instead you can use

for (Map.Entry<String, Collection<Integer>> entry : map.entrySet()){
    String key = entry.getKey();
    for (Integer number : entry.getValye()){
        //here we have access to <key, number> pair, 
        //handle them as you wish;
    }
}



回答3:


While this may be a bit obvious, you can also write:

map.forEach((k, v) -> v.forEach(s -> System.out.println(k + "  " + s)))

Example, in Java 9.

Map< String , Collection< Integer > > map =
    Map.ofEntries(
        Map.entry( "alpha" , List.of( 1 , 2 , 3 ) ) ,
        Map.entry( "beta" , List.of( 4 , 5 , 6 ) ) ,
        Map.entry( "gamma" , List.of( 7 , 8 , 9 ) )
    )
;

map.forEach( ( k , v ) -> {
        v.forEach( s -> System.out.println( k + "  " + s ) );
    }
);



回答4:


Streaming only processes a single value, so you can't get keyValueStream((k,v)-> ...), but you can get keyValueStream(x -> ...) where x is a tuple/pair.

Since you are starting with a Map, which can stream Entry objects (key/value pairs), and you want a key/value pair in your lambda, a stream of Entry objects seems appropriate.

Which means that you just want to flatten the nested collection, e.g. like this:

import java.util.AbstractMap.SimpleEntry;
data.entrySet()
    .stream()
    .flatMap(e -> e.getValue().stream().map(v -> new SimpleEntry<>(e.getKey(), v)))
    // At this point you have a Stream<Entry<String, Integer>> so you can e.g. do this:
    .forEach(e -> System.out.println(e.getKey() + "=" + e.getValue()))
;


来源:https://stackoverflow.com/questions/52357014/how-to-stream-a-map-with-collection-using-java-8-streams

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!