Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert type X to Y in Map<K, Map<V, X>> using Java Stream API

I want to convert inner map from map of maps.

Old map: Map<String, Map<LocalDate, Integer>> Integer means seconds

New map: Map<String, Map<LocalDate, Duration>>

I have tried created new inner map, but got an error

Error: java: no suitable method found for putAll(java.util.stream.Stream<java.lang.Object>) method java.util.Map.putAll(java.util.Map<? extends java.time.LocalDate,? extends java.time.Duration>) is not applicable

oldMap.entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey,
                e -> new HashMap<LocalDate, Duration>() {{
                    putAll(
                        e.getValue().entrySet().stream()
                            .map(x -> new HashMap.SimpleEntry<LocalDate, Duration>
                                (x.getKey(), Duration.ofSeconds(x.getValue())))
                    );
                }}
            ));
like image 277
Alex78191 Avatar asked May 31 '17 11:05

Alex78191


People also ask

Can we convert map to stream in Java?

Converting complete Map<Key, Value> into Stream: This can be done with the help of Map. entrySet() method which returns a Set view of the mappings contained in this map. In Java 8, this returned set can be easily converted into a Stream of key-value pairs using Set. stream() method.

How do I convert a map to a string in Java?

We can convert a map to a string in java using two array lists. In this, we first fill the map with the keys. Then, we will use keySet() method for returning the keys in the map, and values() method for returning the value present in the map to the ArrayList constructor parameter.

How do you filter a stream map?

Since our filter condition requires an int variable we first need to convert Stream of String to Stream of Integer. That's why we called the map() function first. Once we have the Stream of Integer, we can apply maths to find out even numbers. We passed that condition to the filter method.


1 Answers

If you want compact code, you may use

Map<String, Map<LocalDate, Duration>> newMap = new HashMap<>();
oldMap.forEach((s,o) -> o.forEach((d, i) ->
    newMap.computeIfAbsent(s, x->new HashMap<>()).put(d, Duration.ofSeconds(i))));

If you want to avoid unnecessary hash operations, you may expand it a bit

Map<String, Map<LocalDate, Duration>> newMap = new HashMap<>();
oldMap.forEach((s,o) -> {
    Map<LocalDate, Duration> n = new HashMap<>();
    newMap.put(s, n);
    o.forEach((d, i) -> n.put(d, Duration.ofSeconds(i)));
});
like image 143
Holger Avatar answered Sep 30 '22 11:09

Holger