Рубрики
Без рубрики

Инициализация хэш-карты в Java

Изучите различные способы инициализации карты, в частности, для создания пустых, одноэлементных, неизменяемых и изменяемых карт.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы узнаем о различных способах инициализации HashMap в Java.

Мы будем использовать Java 8, а также Java 9.

Дальнейшее чтение:

Сравнение двух хэш-карт в Java

Работа С Картами С Использованием Потоков

2. Статический инициализатор для статической хэш-карты

Мы можем инициализировать HashMap с помощью статического блока кода:

public static Map articleMapOne;
static {
    articleMapOne = new HashMap<>();
    articleMapOne.put("ar01", "Intro to Map");
    articleMapOne.put("ar02", "Some article");
}

Преимущество такого рода инициализации заключается в том, что карта изменчива, но она будет работать только для статики. Следовательно, записи могут быть добавлены и удалены по мере необходимости.

Давайте пойдем дальше и проверим это:

@Test
public void givenStaticMap_whenUpdated_thenCorrect() {
    
    MapInitializer.articleMapOne.put(
      "NewArticle1", "Convert array to List");
    
    assertEquals(
      MapInitializer.articleMapOne.get("NewArticle1"), 
      "Convert array to List");  
}

Мы также можем инициализировать карту, используя синтаксис двойной скобки:

Map doubleBraceMap  = new HashMap() {{
    put("key1", "value1");
    put("key2", "value2");
}};

Обратите внимание, что мы должны стараться избегать этого метода инициализации, потому что он создает анонимный дополнительный класс при каждом использовании, содержит скрытые ссылки на заключающий объект и может вызвать проблемы с утечкой памяти.

3. Использование Коллекций Java

Если нам нужно создать одноэлементную неизменяемую карту с одной записью, Collections.singletonMap() становится очень полезным:

public static Map createSingletonMap() {
    return Collections.singletonMap("username1", "password1");
}

Обратите внимание, что карта здесь неизменна, и если мы попытаемся добавить больше записей, она выдаст java.lang.Исключение UnsupportedOperationException.

Мы также можем создать неизменяемую пустую карту с помощью Collections.emptyMap():

Map emptyMap = Collections.emptyMap();

4. Путь Java 8

В этом разделе давайте рассмотрим способы инициализации карты с помощью Java 8 Stream API.

4.1. Использование коллекторов.toMap()

Давайте используем Поток двумерного строкового массива и соберем их в карту:

Map map = Stream.of(new String[][] {
  { "Hello", "World" }, 
  { "John", "Doe" }, 
}).collect(Collectors.toMap(data -> data[0], data -> data[1]));

Обратите внимание, что здесь тип данных ключа и значение Map одинаковы.

Чтобы сделать его более универсальным, давайте возьмем массив Объектов и выполним ту же операцию:

 Map map = Stream.of(new Object[][] { 
     { "data1", 1 }, 
     { "data2", 2 }, 
 }).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));

В результате мы создаем карту ключа в виде Строки и значения в виде Целого числа .

4.2. Использование потока Map.Entry

Здесь мы будем использовать экземпляры Map.Entry. Это еще один подход, при котором у нас разные типы ключей и значений.

Во-первых, давайте использовать Простой ввод реализацию интерфейса Ввода :

Map map = Stream.of(
  new AbstractMap.SimpleEntry<>("idea", 1), 
  new AbstractMap.SimpleEntry<>("mobile", 2))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Теперь давайте создадим карту с помощью SimpleImmutableEntry реализация:

Map map = Stream.of(
  new AbstractMap.SimpleImmutableEntry<>("idea", 1),    
  new AbstractMap.SimpleImmutableEntry<>("mobile", 2))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

4.3. Инициализация неизменяемой карты

В некоторых случаях использования нам необходимо инициализировать неизменяемую карту. Это можно сделать, обернув Collectors.toMap() внутрь Collectors.collectingAndThen() :

Map map = Stream.of(new String[][] { 
    { "Hello", "World" }, 
    { "John", "Doe" },
}).collect(Collectors.collectingAndThen(
    Collectors.toMap(data -> data[0], data -> data[1]), 
    Collections:: unmodifiableMap));

Обратите внимание, что мы должны избегать использования такой инициализации с помощью Потоки, поскольку это может привести к огромным накладным расходам на производительность, и для инициализации карты создается множество объектов мусора.

5. Путь Java 9

Java 9 поставляется с различными заводскими методами в интерфейсе Map , которые упрощают создание и инициализацию неизменяемых карт.

Давайте продолжим и рассмотрим эти заводские методы.

5.1. Карта.()

Этот фабричный метод не принимает аргументов, один аргумент и переменные аргументы:

Map emptyMap = Map.of();
Map singletonMap = Map.of("key1", "value");
Map map = Map.of("key1","value1", "key2", "value2");

Обратите внимание, что этот метод поддерживает не более 10 пар ключ-значение.

5.2. Карта записей()

Он похож на Map.of () , но не имеет ограничений на количество пар ключ-значение:

Map map = Map.ofEntries(
  new AbstractMap.SimpleEntry("name", "John"),
  new AbstractMap.SimpleEntry("city", "budapest"),
  new AbstractMap.SimpleEntry("zip", "000000"),
  new AbstractMap.SimpleEntry("home", "1231231231")
);

Обратите внимание, что заводские методы создают неизменяемые карты, поэтому любая мутация приведет к исключению UnsupportedOperationException.

Кроме того, они не допускают нулевых ключей или дубликатов ключей.

Теперь, если нам нужна изменяемая или растущая карта после инициализации, мы можем создать любую из реализаций интерфейса Map и передать эти неизменяемые карты в конструктор:

Map map = new HashMap (
  Map.of("key1","value1", "key2", "value2"));
Map map2 = new HashMap (
  Map.ofEntries(
    new AbstractMap.SimpleEntry("name", "John"),    
    new AbstractMap.SimpleEntry("city", "budapest")));

6. Использование Гуавы

Поскольку мы рассмотрели способы использования ядра Java, давайте продолжим и инициализируем карту с помощью библиотеки Guava:

Map articles 
  = ImmutableMap.of("Title", "My New Article", "Title2", "Second Article");

Это позволило бы создать неизменяемую карту и создать изменяемую:

Map articles 
  = Maps.newHashMap(ImmutableMap.of("Title", "My New Article", "Title2", "Second Article"));

Метод ImmutableMap.of() также имеет перегруженные версии, которые могут принимать до 5 пар параметров ключ-значение. Вот как будет выглядеть пример с 2 парами параметров:

ImmutableMap.of("key1", "value1", "key2", "value2");

7. Заключение

В этой статье мы рассмотрели различные способы инициализации Map , в частности, для создания пустых, одноэлементных, неизменяемых и изменяемых карт. Как мы видим, с Java 9 в этой области произошли огромные улучшения.

Как всегда, пример исходного кода находится в проекте Github . Примеры Java 9 находятся здесь , а образец гуавы здесь .