Добавленные в Java 9 методы Map.of, Map.ofEntries и Map.copyOf(также называемые фабричными методами ) очень удобны для быстрого и легкого создания и заполнения неизменяемых объектов Map.
В этом уроке по Java мы научимся создавать неизменяемые/немодифицируемые экземпляры Map с помощью этих фабричных методов и без них.
1. Создание неизменяемой карты, начиная с Java 9
1.1. Создание неизменяемой карты с 10 парами ключ-значение
Начиная с JDK 9, мы можем положиться на фабричный метод Map.of() для создания неизменяемой Map(с максимум 10 парами ключ-значение) [ JEP-269 ]. Map.of() — это перегруженный метод, который принимает от 0 до 10 пар ключ-значение.
Map<String, String> imap = Map.of("key 1", "value 1","key 2", "value 2","key 3", "value 3");
Карты, созданные через Map.of(), не допускают нулевые ключи или значения. Такие попытки приведут к исключению NullPointerException.
Map<String, String> imap = Map.of("key 1", null);
Ошибка программы:
Exception in thread "main" java.lang.NullPointerExceptionat java.base/java.util.Objects.requireNonNull(Objects.java:233)at java.base/java.util.ImmutableCollections$MapN.<init>(ImmutableCollections.java:1193)at java.base/java.util.Map.of(Map.java:1407)
1.2. Создание неизменяемой карты, содержащей более 10 пар ключ-значение
Когда нам нужно добавить более 10 пар ключ-значение в неизменяемую Map, мы можем положиться на метод фабрики Map.ofEntries(). Метод ofEntries() принимает varargs типа Entry, поэтому мы можем передать любое количество пар ключ-значение.
Map<String, String> imap = Map.ofEntries(entry("key 1", "value 1"),entry("key 2", "value 2"),entry("key 3", "value 3"),entry("key 4", "value 4"),entry("key 5", "value 5"),entry("key 6", "value 6"),entry("key 7", "value 7"),entry("key 8", "value 8"),entry("key 9", "value 9"),entry("key 10", "value 10"),entry("key 11", "value 11"),entry("key 12", "value 12"));
Обратите внимание, что нулевые ключи или значения также не допускаются в методе ofEntries(). Поэтому, пожалуйста, отфильтруйте любой нулевой ключ или значение перед вызовом метода Map.entry().
1.3. Создать неизменяемую карту из изменяемой карты
Другой фабричный метод Map.copyOf() был добавлен в Java 10, который может помочь вам в создании неизменяемых Maps из заданной изменяемой карты. Опять же, изменяемая карта не должна содержать никаких нулевых ключей или значений.
Map<String, String> map = new HashMap<>();map.put("key 1", "value 1");map.put("key 2", "value 2");map.put("key 3", "value 3");Map<String, String> imap = Map.copyOf(map);
Если данная Map впоследствии будет изменена, возвращаемая Map не будет отражать такие изменения. В следующем примере мы видим, что когда исходная изменяемая карта была изменена, это не повлияло на неизменяемую карту, созданную с помощью метода copyOf().
Map<String, String> map = new HashMap<>();map.put("key 1", "value 1");map.put("key 2", "value 2");map.put("key 3", "value 3");Map<String, String> imap = Map.copyOf(map);//modify the original mapmap.put("key 4", "value 4");System.out.println(map); // {key 4=value 4, key 3=value 3, key 2=value 2, key 1=value 1}System.out.println(imap); // {key 3=value 3, key 1=value 1, key 2=value 2}
1.4 Сбор пар ключ-значение из потока в неизменяемую карту
Java Streams отлично подходят для конвейерных методов и выполнения нескольких действий над коллекцией элементов в последовательности. После обработки элементов Stream мы можем собрать их в неизменяемую Map следующим образом:
Map<String, String> imap = Stream.of(entry("key 1", "value 1"),entry("key 2", "value 2"),entry("key 3", "value 3")).collect(toUnmodifiableMap(e->e.getKey(), e->e.getValue()));
2. Создание неизменяемой карты в Java 8
Если ваше приложение работает на Java 8, то первая рекомендация — обновить JDK до последней версии. Было сделано так много улучшений производительности и API, и вы получите от них большую выгоду.
В Java 8 самый простой способ создания неизменяемой карты — это использование метода Collections.unmodifiableMap(). Это очень полезно, поскольку позволяет нам создать неизменяемую карту из изменяемой.
Map<Integer, String> map = new HashMap<>();map.put("key 1", "value 1");map.put("key 2", "value 2");map.put("key 3", "value 3");......Map<Integer, String> imap = Collections.unmodifiableMap(map);//immutableMap.put("key2", "value2"); // throws java.lang.UnsupportedOperationException
Если вы собираете пары ключ-значение из Stream, то Collectors.toMap() можно использовать в дополнение к Collections::unmodifiableMap. В следующем примере у нас есть Stream java.util.Map.entry, и мы собираем их в неизменяемую карту.
Map<Integer, String> imap = Stream.of(entry("key 1", "value 1"),entry("key 2", "value 2"),entry("key 3", "value 3")).collect(collectingAndThen(toMap(e -> e.getKey(), e -> e.getValue()), Collections::unmodifiableMap));
3. Резюме
В этом кратком руководстве по Java мы научились создавать неизменяемую или немодифицируемую карту с помощью метода factory, добавленного в Java 9 и более поздних версиях. Мы также научились создавать неизменяемые карты с помощью API Java 8.