迭代和复制HashMap值的有效方法


9

我要转换:

Map<String, Map<String, List<Map<String, String>>>> inputMap 

至:

Map<String, Map<String, CustomObject>> customMap

inputMap在配置中提供并准备就绪,但我需要customMap格式化。CustomObject将派生自List<Map<String, String>>在函数中使用几行代码。

我尝试了一种迭代输入映射并在customMap中复制键值的常规方法。使用Java 8或其他快捷方式有什么有效的方法吗?

Map<String, Map<String, List<Map<String, String>>>> configuredMap = new HashMap<>();
Map<String, Map<String, CustomObj>> finalMap = new HashMap<>();


for (Map.Entry<String, Map<String, List<Map<String, String>>>> attributeEntry : configuredMap.entrySet()) {
    Map<String, CustomObj> innerMap = new HashMap<>();
    for (Map.Entry<String, List<Map<String, String>>> valueEntry : attributeEntry.getValue().entrySet()) {
        innerMap.put(valueEntry.getKey(), getCustomeObj(valueEntry.getValue()));
    }
    finalMap.put(attributeEntry.getKey(), innerMap);
}

private CustomObj getCustomeObj(List<Map<String, String>> list) {
    return new CustomObj();
}

请正确格式化代码。
akuzminykh

1
您是否考虑过创建外观而不是复制外观?
ControlAltDel

没有任何更有效的方法。所有这些操作都必须进行。但是此代码实际上不起作用。您没有将列表放入自定义对象。
user207421

Answers:


2

一种解决方案是流式传输entrySetinputMap,然后用Collectors#toMap两次(用于外部一次Map,并且一旦对于所述内Map):

Map<String, Map<String, CustomObj>> customMap = inputMap.entrySet()
        .stream()
        .collect(Collectors.toMap(Function.identity(), entry -> {
            return entry.getValue()
                        .entrySet()
                        .stream()
                        .collect(Collectors.toMap(Function.identity(), 
                            entry -> getCustomeObj(entry.getValue())));
        }));

您可以{}在lambda中省略和return语句,如下所示:.collect(Collectors.toMap(Function.identity(), entry -> entry.getValue() .entrySet() .stream() .collect(Collectors.toMap(Function.identity(), entry -> getCustomeObj(entry.getValue()))); ));
SHoko

3
@SHoko是的,但是我认为如果没有该块,它的可读性就会降低。
雅各布·G

1

您可以流式传输,但是看起来不可读。至少对我来说 因此,如果您有一种方法:

static CustomObject fun(List<Map<String, String>> in) {
    return .... // whatever processing you have here
}

您仍然可以使用java-8语法,但是格式不同:

    Map<String, Map<String, CustomObject>> customMap = new HashMap<>();

    inputMap.forEach((key, value) -> {

        value.forEach((innerKey, listOfMaps) -> {

            Map<String, CustomObject> innerMap = new HashMap<>();
            innerMap.put(innerKey, fun(listOfMaps));
            customMap.put(key, innerMap);

        });
    });

如果可以制作内部地图immutable,则可以使它更短:

inputMap.forEach((key, value) -> {
      value.forEach((innerKey, listOfMaps) -> {
          customMap.put(key, Collections.singletonMap(innerKey, fun(listOfMaps)));
      });
});

1

恕我直言流不是一个坏主意。没有糟糕的工具。这取决于您如何使用它们。


在这种特殊情况下,我会将重复模式提取到实用程序方法中:

public static <K, V1, V2> Map<K, V2> transformValues(Map<K, V1> map, Function<V1, V2> transformer) {
    return map.entrySet()
              .stream()
              .collect(toMap(Entry::getKey, e -> transformer.apply(e.getValue())));
}

上面的方法可以使用任何方法来实现,尽管我认为Stream API这里非常合适。


定义了实用程序方法后,即可按以下简单方式使用它:

Map<String, Map<String, CustomObj>> customMap = 
    transformValues(inputMap, attr -> transformValues(attr, this::getCustomObj));

实际的转换实际上是一个班轮。因此,使用适当的JavaDocfor transformValues方法,结果代码非常易于阅读和维护。


1

Collectors.toMap外部和内部条目的输入方式如何,例如:

Map<String, Map<String, CustomObj>> finalMap = configuredMap.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                attributeEntry -> attributeEntry.getValue().entrySet()
                        .stream()
                        .collect(Collectors.toMap(Map.Entry::getKey,
                                valueEntry -> getCustomeObj(valueEntry.getValue())))));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.