In Java, the Map.copyOf() method, introduced in Java 10, is a factory method used to create an unmodifiable (immutable) copy of a given Map. This method ensures that the resulting Map cannot be modified, and attempting to do so throws an UnsupportedOperationException.
Here’s how to use it effectively:
Syntax:
public static <K,V> Map<K,V> copyOf(Map<? extends K,? extends V> map)
- Parameters: A single map (
Map<? extends K, ? extends V>to copy). - Returns: An unmodifiable copy of the given map.
- Throws:
NullPointerExceptionif the provided map or any of its keys/values isnull(this method does not allownullas keys or values).IllegalArgumentExceptionif there are duplicate keys in the map.
Examples
1. Creating an Immutable Map from an Existing Map
package org.kodejava.util;
import java.util.Map;
public class MapCopyOfExample {
public static void main(String[] args) {
// Original mutable map
Map<Integer, String> originalMap = Map.of(1, "One", 2, "Two", 3, "Three");
// Creating an immutable copy
Map<Integer, String> immutableMap = Map.copyOf(originalMap);
// Attempting to modify will throw UnsupportedOperationException
System.out.println(immutableMap); // Output: {1=One, 2=Two, 3=Three}
// Uncommenting the following line will throw an error
// immutableMap.put(4, "Four");
}
}
2. Avoiding Redundant Copies
Map.copyOf() avoids redundant copying. If the input Map is already unmodifiable (e.g., created using Map.copyOf() or Map.of()), it simply returns the same instance.
Map<String, String> immutableMap1 = Map.of("Key1", "Value1", "Key2", "Value2");
// Reusing the immutable instance
Map<String, String> immutableMap2 = Map.copyOf(immutableMap1);
System.out.println(immutableMap1 == immutableMap2); // Output: true
3. Copying a Mutable Map
A mutable map can be made immutable using Map.copyOf().
package org.kodejava.util;
import java.util.HashMap;
import java.util.Map;
public class MutableToImmutable {
public static void main(String[] args) {
// Create a mutable map
Map<String, String> mutableMap = new HashMap<>();
mutableMap.put("A", "Apple");
mutableMap.put("B", "Banana");
// Make an immutable copy
Map<String, String> immutableMap = Map.copyOf(mutableMap);
// Attempting to modify the copy throws an exception
System.out.println(immutableMap); // Output: {A=Apple, B=Banana}
// mutableMap.put("C", "Cherry"); // Allowed for mutableMap
// immutableMap.put("C", "Cherry"); // Throws UnsupportedOperationException
}
}
Notes about Map.copyOf()
- Null Values/Keys:
- Both keys and values must be non-null; otherwise, a
NullPointerExceptionwill be thrown.
- Both keys and values must be non-null; otherwise, a
- Immutable Nature:
- The map returned is truly immutable. Not only are modifications disallowed, but if the input map is mutable, changes to the input do not affect the immutable map.
- Alternative Methods:
Map.of()can also be used to create immutable maps directly, but it requires you to specify the entries upfront.
Key Differences: Map.copyOf() vs Map.of()
| Feature | Map.copyOf() |
Map.of() |
|---|---|---|
| Input | Accepts an existing map | Accepts individual key-value pairs |
| Suitability for Copy | Used to copy an existing map | Used to create new map |
| Duplicates | Rejects duplicates in the source map | Doesn’t allow duplicates |
| Empty Map | Works with an empty map | Use Map.of() for emptiness |
Summary
The Map.copyOf() method is a lightweight way to create immutable maps, especially from existing maps. It’s perfect for ensuring immutability and avoiding unintentional modifications to data structures. Use it where immutability is key, such as shared configurations, constants, or thread-safe data sharing!
