HashMap değerlerini yinelemenin ve kopyalamanın etkili yolu


9

Dönüştürmek istiyorum:

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

için:

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

inputMapyapılandırmada sağlanır ve hazırdır ancak customMapBiçimlendirmem gerekiyor . CustomObject, List<Map<String, String>>bir işlevde birkaç kod satırı kullanılarak türetilir .

Giriş haritası yineleme ve customMap anahtar değerleri kopyalama normal bir yol denedim. Java 8 veya başka bir kısayol kullanarak bunu yapmanın etkili bir yolu var mı?

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();
}

Lütfen kodu doğru şekilde biçimlendirin.
akuzminykh

1
Kopyalamak yerine bir cephe oluşturmayı düşündünüz mü?
ControlAltDel

Daha etkili bir yol olamaz. Tüm bu operasyonların gerçekleşmesi gerekiyor. Ancak bu kod aslında çalışmıyor. Listeyi özel nesneye koymuyorsunuz.
user207421

Yanıtlar:


2

Bir çözüm akarsu entrySetarasında inputMap, ve daha sonra kullanmak Collectors#toMapiki kez (dış bir kez Mapve iç kez 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())));
        }));

{}.collect(Collectors.toMap(Function.identity(), entry -> entry.getValue() .entrySet() .stream() .collect(Collectors.toMap(Function.identity(), entry -> getCustomeObj(entry.getValue()))); ));
Lambda'daki

3
@SHoko True, ama blok olmadan daha az okunabilir görüneceğini düşünüyorum.
Jacob G.13

1

Akış yapabilirsiniz, ancak bu okunabilir görünmeyecek; en azından bana. Yani bir yönteminiz varsa:

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

java-8sözdizimini kullanmaya devam edebilirsiniz , ancak farklı bir biçimde kullanabilirsiniz:

    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);

        });
    });

İç haritayı yapabilirseniz immutable, bunu daha da kısaltabilirsiniz:

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

1

IMHO akışı o kadar da kötü bir fikir değil. Kötü araçlar yok. Bunları nasıl kullandığınıza bağlıdır.


Bu özel durumda, yinelenen kalıbı bir yardımcı yönteme çıkaracağım:

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())));
}

Yukarıdaki yöntem herhangi bir yaklaşım kullanılarak uygulanabilir, ancak Stream APIburada oldukça iyi uyuyor.


Yardımcı program yöntemini tanımladıktan sonra, aşağıdaki gibi basit bir şekilde kullanılabilir:

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

Gerçek dönüşüm etkili bir şekilde bir astardır. Yani doğru ile JavaDociçin transformValuesyöntemin sonuç kodu oldukça okunabilir ve sürdürülebilir olduğunu.


1

Nasıl hakkında Collectors.toMapbir dış ve iç seviyede gibi girdilerin her ikisi için:

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())))));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.