Reputation: 36051
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...
Upvotes: 1
Views: 11935
Reputation: 121048
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 ) );
}
);
Upvotes: 2
Reputation: 16039
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)));
Upvotes: 5
Reputation: 124275
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;
}
}
Upvotes: 3
Reputation: 159215
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()))
;
Upvotes: 1