수정 불가능한 Map(Unmodifiable Map)이란 한 번 생성되면 키(key)와 값(value)을 추가, 삭제 또는 수정할 수 없는 Map을 말합니다. Java 9에서는 Map 인터페이스에 추가된 정적 팩토리 메서드인 Map.of()와 Map.ofEntries()를 사용해 이러한 불변 Map을 매우 간편하게 생성할 수 있습니다.
이 두 메서드로 생성된 Map 인스턴스는 다음과 같은 특징을 가집니다.
- 팩토리 메서드가 반환하는 Map은 사실상 불변(immutable)입니다. 즉, 키와 값을 추가, 삭제, 변경할 수 없으며, 변경 메서드(mutator)를 호출하면 UnsupportedOperationException이 발생합니다.
- Map에 담긴 키나 값 자체가 가변(mutable) 객체라면, Map의 내용이 실제로 변경되어 일관성 없게 동작할 수 있습니다.
- 불변 Map은 null 키와 null 값을 허용하지 않습니다. null 키 또는 null 값으로 생성을 시도하면 NullPointerException이 발생합니다.
- 중복된 키는 생성 시점에 바로 거부됩니다. 중복 키를 정적 팩토리 메서드에 전달하면 IllegalArgumentException이 발생합니다.
- 모든 키와 값이 직렬화 가능하다면 불변 Map 역시 직렬화(serializable) 가능합니다.
- 항목(entry)의 반복 순서는 보장되지 않으며(unspecified), 언제든 변경될 수 있습니다.
문법
Map.of(k1, v1, k2, v2) Map.ofEntries(entry(k1, v1), entry(k2, v2), ...)
Map.of() 예제
import java.util.Map;
public class UnmodifiableMapTest {
public static void main(String[] args) {
Map<String, String> empMap = Map.of("101", "Raja", "102", "Adithya", "103", "Jai", "104", "Chaitanya");
System.out.println("empMap - " + empMap);
empMap.put("105", "Vamsi"); // UnsupportedOperationException 발생
}
}실행 결과
empMap - {104=Chaitanya, 103=Jai, 102=Adithya, 101=Raja}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(Unknown Source)
at java.base/java.util.ImmutableCollections$AbstractImmutableMap.put(Unknown Source)
at UnmodifiableMapTest.main(UnmodifiableMapTest.java:7)위 예제에서 볼 수 있듯이, 이미 생성된 불변 Map에 새 항목을 추가하려고 하면 런타임 시점에 UnsupportedOperationException이 던져집니다.
Map.ofEntries() 예제
import java.util.Map;
import static java.util.Map.entry;
public class UnmodifiableMapTest {
public static void main(String[] args) {
Map<String, String> empMap = Map.ofEntries(entry("101", "Raja"), entry("102", "Adithya"), entry("103", "Jai"), entry("104", "Chaitanya"));
System.out.println("empMap - " + empMap);
}
}실행 결과
empMap - {102=Adithya, 101=Raja, 104=Chaitanya, 103=Jai}Map.of()는 최대 10개의 키-값 쌍까지만 지원하는 반면, Map.ofEntries()는 가변 인자(varargs)를 사용하기 때문에 그 이상의 많은 항목도 손쉽게 담을 수 있다는 장점이 있습니다. 따라서 소량의 데이터에는 Map.of()를, 더 많은 데이터나 가독성이 중요한 경우에는 Map.ofEntries()를 사용하는 것이 좋습니다.