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

답변:


2

한 가지 해결책은 entrySetof of 를 스트리밍 inputMap한 다음 Collectors#toMap두 번 사용하는 것입니다 (한 번은 outer Map및 한 번은 inner 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())));
        }));

{}다음과 같이 람다에서 및 return 문을 생략 할 수 있습니다 ..collect(Collectors.toMap(Function.identity(), entry -> entry.getValue() .entrySet() .stream() .collect(Collectors.toMap(Function.identity(), entry -> getCustomeObj(entry.getValue()))); ));
SHoko

3
@ SHoko 사실이지만 블록이 없으면 읽기 어려워 보일 것입니다.
Jacob 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

IMHO 스트리밍은 그렇게 나쁘지 않습니다. 나쁜 도구는 없습니다. 사용 방법에 따라 다릅니다.


이 특별한 경우에는 반복되는 패턴을 유틸리티 메소드로 추출합니다.

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

실제 변형은 사실상 하나의 라이너입니다. 그래서 적절한에 JavaDoc대한 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())))));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.