Java/컬렉션

[Java]HashMap 합치는 방법

DevStory 2022. 8. 31.

HashMap 합치는 방법

이번 포스팅은 두 개의 HashMap을 합치는 몇 가지 방법을 소개합니다.


방법 1. HashMap의 putAll 메서드

첫 번째 방법으로 HashMap 클래스에서 제공하는 putAll() 메서드를 사용합니다.

public void putAll(Map<? extends K, ? extends V> m);

A와 B라는 두 개의 HashMap 객체가 존재한다고 가정합시다. A가 putAll() 메서드를 호출하고 매개변수로 B를 전달하면, A는 B를 값을 포함합니다. B의 값은 변경되지 않습니다.

 

다음 예제는 putAll() 메서드를 사용하여 두 개의 HashMap을 합칩니다.

public static void main(String args[]) {
  HashMap<String, Integer> hm1 = new HashMap<>();
  hm1.put("A", 100);
  hm1.put("B", 200);
  hm1.put("C", 300);

  HashMap<String, Integer> hm2 = new HashMap<>();
  hm2.put("C", 500);
  hm2.put("D", 200);
  hm2.put("E", 300);

  System.out.println("[합치기 전]");
  System.out.println("hm1: " + hm1);
  System.out.println("hm2: " + hm2);

  hm1.putAll(hm2);

  System.out.println("\n[합친 후]");
  System.out.println("hm1: " + hm1);
  System.out.println("hm2: " + hm2);
}

[실행 결과]

[합치기 전]
hm1: {A=100, B=200, C=300}
hm2: {C=500, D=200, E=300}

[합친 후]
hm1: {A=100, B=200, C=500, D=200, E=300}
hm2: {C=500, D=200, E=300}

실행 결과에서 확인할 수 있듯이 두 HashMap이 동일한 키를 가지고 있으면, putAll() 메서드에 전달된 HashMap의 값으로 변경됩니다.


방법 2. foreach 메서드와 merge 메서드

두 번째 방법으로 HashMap에서 foreach() 메서드를 호출하여 키와 값을 접근한 뒤 HashMap에 요소를 병합하는 merge() 메서드를 호출합니다.

 

참고로 HashMap의 merge() 메서드를 사용하기 위해서는 Java의 버전이 1.8 이상이어야 합니다.

public V merge(
  K key, 
  V value,
  BiFunction<? super V, ? super V, ? extends V> remappingFunction);

merge() 메서드를 사용하는 방법의 장점은 두 HashMap에 동일한 키가 존재하는 경우 값을 설정할 수 있습니다.

 

다음 예제는 HashMap 객체인 hm2를 foreach() 메서드로 순회하며, hm1에 hm2의 요소를 병합하는 merge() 메서드를 호출합니다.

public static void main(String args[]) {
  HashMap<String, Integer> hm1 = new HashMap<>();
  hm1.put("A", 100);
  hm1.put("B", 200);
  hm1.put("C", 300);

  HashMap<String, Integer> hm2 = new HashMap<>();
  hm2.put("C", 500);
  hm2.put("D", 200);
  hm2.put("E", 300);

  System.out.println("[합치기 전]");
  System.out.println("hm1: " + hm1);
  System.out.println("hm2: " + hm2);

  // v1은 hm1의 Value
  // v2는 hm2의 Value
  hm2.forEach((key, value) ->
          hm1.merge(key, value, (v1, v2) -> v1 + v2));

  System.out.println("\n[합친 후]");
  System.out.println("hm1: " + hm1);
  System.out.println("hm2: " + hm2);
}

[실행 결과]

[합치기 전]
hm1: {A=100, B=200, C=300}
hm2: {C=500, D=200, E=300}

[합친 후]
hm1: {A=100, B=200, C=800, D=200, E=300}
hm2: {C=500, D=200, E=300}

실행 결과에서 확인할 수 있듯이 두 HashMap은 문자열 "C"라는 동일한 키가 존재합니다. merge() 메서드에서 동일한 키가 존재하는 경우 기존 값을 합산된 값으로 변경합니다.

 

위 예제처럼 HashMap의 값을 원하는 값으로 설정할 수 있습니다.


방법 3. Stream API

마지막 방법으로 Stream에서 제공하는 메서드를 사용하여 두 HashMap을 하나로 합치고 새로운 HashMap을 생성할 수 있습니다.

 

단일 스트림을 Map으로 변환하기 위해 collect() 메서드의 매개변수로 Collectors 클래스의 toMap() 메서드를 호출합니다.

public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                    Function<? super T, ? extends U> valueMapper,
                                    BinaryOperator<U> mergeFunction);

toMap() 메서드는 오버로드된 버전이 여러 개 존재하는데, 두 HashMap에 겹치는 키가 존재할 수 있으므로 세 번째 매개변수가 BinaryOperator 타입인 toMap() 메서드를 사용해야 합니다.

 

[합치는 방법]

순서 1. 두 개의 HashMap을 단일 스트림으로 변환합니다.

순서 2. collect() 메서드에서 변환된 스트림을 Map으로 변환합니다.

public static void main(String args[]) {
  HashMap<String, Integer> hm1 = new HashMap<>();
  hm1.put("A", 100);
  hm1.put("B", 200);
  hm1.put("C", 300);

  HashMap<String, Integer> hm2 = new HashMap<>();
  hm2.put("C", 500);
  hm2.put("D", 200);
  hm2.put("E", 300);

  System.out.println("[합치기 전]");
  System.out.println("hm1: " + hm1);
  System.out.println("hm2: " + hm2);

  Map<String, Integer> hm3 = Stream.of(hm1, hm2)
          .flatMap(m -> m.entrySet().stream())
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                  (oldValue, newValue) -> oldValue));

  System.out.println("\n[합친 후]");
  System.out.println("hm1: " + hm1);
  System.out.println("hm2: " + hm2);
  System.out.println("hm3: " + hm3);
}

[실행 결과]

[합치기 전]
hm1: {A=100, B=200, C=300}
hm2: {C=500, D=200, E=300}

[합친 후]
hm1: {A=100, B=200, C=300}
hm2: {C=500, D=200, E=300}
hm3: {A=100, B=200, C=300, D=200, E=300}
반응형

댓글