使用Java Stream API将类型X转换为Map <K,Map <V,X >>中的Y.

Ale*_*191 17 java dictionary java-8 java-stream collectors

我想从地图地图转换内部地图.

旧地图:Map<String, Map<LocalDate, Integer>>整数表示秒

新地图: Map<String, Map<LocalDate, Duration>>

我试过创建了新的内部地图,但是出了错误

错误:java:找不到适合方法的putAll(java.util.stream.Stream<java.lang.Object>) 方法java.util.Map.putAll(java.util.Map<? extends java.time.LocalDate,? extends java.time.Duration>)不适用

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())))
                    );
                }}
            ));
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 11

如果你想要紧凑的代码,你可以使用

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))));
Run Code Online (Sandbox Code Playgroud)

如果要避免不必要的哈希操作,可以稍微扩展一下

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)));
});
Run Code Online (Sandbox Code Playgroud)


And*_*ure 8

快速而干净

HashMap<String, HashMap<LocalDate, Duration>> newMap = new HashMap<>();
oldHashMap.forEach((key, innerMap) -> {
    HashMap<LocalDate, Duration> newStuff = new HashMap<>();
    innerMap.forEach((k2,v2) -> newStuff.put(k2,Duration.ofSeconds(v2)));
    newMap.put(key, newStuff);
});
Run Code Online (Sandbox Code Playgroud)


Eug*_*ene 5

还有一个......

 Map<String, Map<LocalDate, Duration>> newMap = map.entrySet().stream().collect(
            Collectors.toMap(Entry::getKey,
                    entry -> entry.getValue().entrySet().stream().collect(
                            Collectors.toMap(Entry::getKey, e -> Duration.ofSeconds(e.getValue())))));
Run Code Online (Sandbox Code Playgroud)


Bor*_*der 5

我的两分钱,创建一个方法转换Map<K, V1>Map<K, V2>:

public static <K,V1,V2> Map<K, V2> transformValues(final Map<K, V1> input, final Function<V1,V2> transform) {
    Function<Map.Entry<K, V1>, V2> mapper = transform.compose(Map.Entry::getValue);
    return input.entrySet().stream()
            .collect(toMap(Map.Entry::getKey, mapper));
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码变成:

Map<String, Map<LocalDate, Duration>> transformed 
    = transformValues(maps, map -> transformValues(map, Duration::ofSeconds));
Run Code Online (Sandbox Code Playgroud)


Ste*_*ski 3

我更愿意迭代旧地图的条目并流过内部地图:

for (Entry<String, Map<LocalDate, Integer>> entry : oldMap.entrySet()) {
    Map<LocalDate, Duration> asDuration = entry.getValue().entrySet().stream()
        .collect(Collectors.toMap(e -> e.getKey(), e -> Duration.ofSeconds(e.getValue().longValue())));
    newMap.put(entry.getKey(), asDuration);
}
Run Code Online (Sandbox Code Playgroud)

否则你需要在你的内部有第二个流collect

newMap = oldMap.entrySet().stream()
        .collect(Collectors.toMap(s -> s.getKey(), s -> s.getValue().entrySet().stream()
        .collect(Collectors.toMap(e -> e.getKey(), e -> Duration.ofSeconds(e.getValue().longValue())))));
Run Code Online (Sandbox Code Playgroud)