Неизменяемые реализации карт в Java

Неизменные реализации карт в Java

1. обзор

Иногда предпочтительнее запретить модификацииjava.util.Map , такие как совместное использование данных только для чтения между потоками. Для этой цели мы можем использовать либо неизменяемую карту, либо неизменяемую карту.

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

2. Неизменяемые и неизменяемые

Неизменяемая карта - это просто оболочка над изменяемой картой, и она не позволяет вносить в нее изменения напрямую:

Map mutableMap = new HashMap<>();
mutableMap.put("USA", "North America");

Map unmodifiableMap = Collections.unmodifiableMap(mutableMap);
assertThrows(UnsupportedOperationException.class,
  () -> unmodifiableMap.put("Canada", "North America"));

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

mutableMap.remove("USA");
assertFalse(unmodifiableMap.containsKey("USA"));

mutableMap.put("Mexico", "North America");
assertTrue(unmodifiableMap.containsKey("Mexico"));

An Immutable Map, on the other hand, contains its own private data and doesn’t allow modifications to it. Следовательно, данные не могут измениться каким-либо образом после создания экземпляра неизменяемой карты.

3. Неизменяемая карта Гуавы

Guava предоставляет неизменяемые версии каждогоjava.util.Map usingImmutableMap. Он выдаетUnsupportedOperationException всякий раз, когда мы пытаемся его изменить.

Поскольку он содержит собственные личные данные, они не изменятся при изменении исходной карты.

Теперь мы обсудим различные способы создания экземпляровImmutableMap.

3.1. Используя методcopyOf()

Во-первых, давайте воспользуемся методомImmutableMap.copyOf(), который возвращает копии всех записей, как в исходной карте:

ImmutableMap immutableMap = ImmutableMap.copyOf(mutableMap);
assertTrue(immutableMap.containsKey("USA"));

Его нельзя изменить прямо или косвенно:

assertThrows(UnsupportedOperationException.class,
  () -> immutableMap.put("Canada", "North America"));

mutableMap.remove("USA");
assertTrue(immutableMap.containsKey("USA"));

mutableMap.put("Mexico", "North America");
assertFalse(immutableMap.containsKey("Mexico"));

3.2. Используя методbuilder()

Мы также можем использовать методImmutableMap.builder() для создания копии всех записей, как на исходной карте.

Более того, мы можем использовать этот метод для добавления дополнительных записей, которых нет на исходной карте:

ImmutableMap immutableMap = ImmutableMap.builder()
  .putAll(mutableMap)
  .put("Costa Rica", "North America")
  .build();
assertTrue(immutableMap.containsKey("USA"));
assertTrue(immutableMap.containsKey("Costa Rica"));

Как и в предыдущем примере, мы не можем изменить его прямо или косвенно:

assertThrows(UnsupportedOperationException.class,
  () -> immutableMap.put("Canada", "North America"));

mutableMap.remove("USA");
assertTrue(immutableMap.containsKey("USA"));

mutableMap.put("Mexico", "North America");
assertFalse(immutableMap.containsKey("Mexico"));

3.3. Используя методof()

Наконец, мы можем использовать методImmutableMap.of() для создания неизменяемой карты с набором записей, предоставляемых на лету. Он поддерживает не более пяти пар ключ / значение:

ImmutableMap immutableMap
  = ImmutableMap.of("USA", "North America", "Costa Rica", "North America");
assertTrue(immutableMap.containsKey("USA"));
assertTrue(immutableMap.containsKey("Costa Rica"));

Мы не можем изменить это также:

assertThrows(UnsupportedOperationException.class,
  () -> immutableMap.put("Canada", "North America"));

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

В этой быстрой статье мы обсудили различия между неизменяемой картой и неизменной картой.

Мы также рассмотрели различные способы созданияImmutableMap. для Guava.

И, как всегда, доступны полные примеры кодаover on GitHub.