Перейти к основному содержимому

Как создать новую запись на карте

· 4 мин. чтения

1. Обзор

В этом руководстве мы обсудим, как использовать встроенные классы Java, сторонние библиотеки и нашу пользовательскую реализацию для создания объекта Entry , представляющего ассоциацию ключ-значение в Map .

2. Использование встроенных классов Java

Java предоставляет Map . Интерфейс Entry с двумя простыми реализациями для создания Entry . Давайте посмотрим на них.

2.1. Использование Абстрактной карты . Простой ввод

Класс SimpleEntry является статическим вложенным классом в классе AbstractMap . Он предоставляет два разных конструктора для инициализации экземпляра:

AbstractMap.SimpleEntry<String, String> firstEntry = new AbstractMap.SimpleEntry<>("key1", "value1");
AbstractMap.SimpleEntry<String, String> secondEntry = new AbstractMap.SimpleEntry<>("key2", "value2");
AbstractMap.SimpleEntry<String, String> thirdEntry = new AbstractMap.SimpleEntry<>(firstEntry);
thirdEntry.setValue("a different value");

assertThat(Stream.of(firstEntry, secondEntry, thirdEntry))
.extracting("key", "value")
.containsExactly(
tuple("key1", "value1"),
tuple("key2", "value2"),
tuple("key1", "a different value"));

Как мы видим здесь, один из конструкторов принимает ключ и значение, а другой принимает экземпляр Entry для инициализации нового экземпляра Entry .

2.2. Использование Абстрактной карты . SimpleImmutableEntry

Как и в случае с SimpleEntry , мы можем использовать SimpleImmutableEntry для создания записей:

AbstractMap.SimpleImmutableEntry<String, String> firstEntry = new AbstractMap.SimpleImmutableEntry<>("key1", "value1");
AbstractMap.SimpleImmutableEntry<String, String> secondEntry = new AbstractMap.SimpleImmutableEntry<>("key2", "value2");
AbstractMap.SimpleImmutableEntry<String, String> thirdEntry = new AbstractMap.SimpleImmutableEntry<>(firstEntry);

assertThat(Stream.of(firstEntry, secondEntry, thirdEntry))
.extracting("key", "value")
.containsExactly(
tuple("key1", "value1"),
tuple("key2", "value2"),
tuple("key1", "value1"));

В отличие от SimpleEntry , SimpleImmutableEntry не позволяет нам изменять значение после инициализации экземпляра Entry . Если мы попытаемся изменить значение, будет выброшено исключение java.lang.UnsupportedOperationException.

2.3. Использование карты . вход

Начиная с версии 9, Java имеет статический метод entry() в интерфейсе Map для создания Entry :

Map.Entry<String, String> entry = Map.entry("key", "value");

assertThat(entry.getKey()).isEqualTo("key");
assertThat(entry.getValue()).isEqualTo("value");

Мы должны иметь в виду, что запись, созданная таким образом, также является неизменной и приведет к исключению java.lang.UnsupportedOperationException , если мы попытаемся изменить значение после инициализации.

3. Сторонние библиотеки

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

3.1. Использование библиотеки Apache commons-collections4

Давайте начнем с включения нашей зависимости Maven :

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>

Следует отметить, что помимо интерфейса Entry , библиотека также предоставляет интерфейс под названием KeyValue:

Map.Entry<String, String> firstEntry = new DefaultMapEntry<>("key1", "value1");
KeyValue<String, String> secondEntry = new DefaultMapEntry<>("key2", "value2");

KeyValue<String, String> thirdEntry = new DefaultMapEntry<>(firstEntry);
KeyValue<String, String> fourthEntry = new DefaultMapEntry<>(secondEntry);

firstEntry.setValue("a different value");

assertThat(firstEntry)
.extracting("key", "value")
.containsExactly("key1", "a different value");

assertThat(Stream.of(secondEntry, thirdEntry, fourthEntry))
.extracting("key", "value")
.containsExactly(
tuple("key2", "value2"),
tuple("key1", "value1"),
tuple("key2", "value2"));

Класс DefaultMapEntry предоставляет три разных конструктора. В то время как первый принимает пару ключ-значение, второй и третий принимают тип параметра Entry и KeyValue соответственно.

Точно так же ведет себя и класс UnmodifiedMapEntry :

Map.Entry<String, String> firstEntry = new UnmodifiableMapEntry<>("key1", "value1");
KeyValue<String, String> secondEntry = new UnmodifiableMapEntry<>("key2", "value2");

KeyValue<String, String> thirdEntry = new UnmodifiableMapEntry<>(firstEntry);
KeyValue<String, String> fourthEntry = new UnmodifiableMapEntry<>(secondEntry);

assertThat(firstEntry)
.extracting("key", "value")
.containsExactly("key1", "value1");

assertThat(Stream.of(secondEntry, thirdEntry, fourthEntry))
.extracting("key", "value")
.containsExactly(
tuple("key2", "value2"),
tuple("key1", "value1"),
tuple("key2", "value2"));

Однако, как мы можем понять из названия, UnmodifiedMapEntry также не позволяет нам изменять значение после инициализации .

3.2. Использование библиотеки Google Guava

Давайте сначала включим нашу зависимость Maven :

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>

Теперь давайте посмотрим, как мы можем использовать метод immutableEntry() :

Map.Entry<String, String> firstEntry = Maps.immutableEntry("key1", "value1");
Map.Entry<String, String> secondEntry = Maps.immutableEntry("key2", "value2");

assertThat(Stream.of(firstEntry, secondEntry))
.extracting("key", "value")
.containsExactly(
tuple("key1", "value1"),
tuple("key2", "value2"));

Поскольку он создает неизменяемую запись, если мы попытаемся изменить значение, он выдаст исключение java.lang.UnsupportedOperationException.

4. Пользовательская реализация

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

Это означает, что пока мы соблюдаем их, мы можем создать собственную реализацию интерфейса Entry . Во-первых, давайте добавим простую реализацию:

public class SimpleCustomKeyValue<K, V> implements Map.Entry<K, V> {

private final K key;
private V value;

public SimpleCustomKeyValue(K key, V value) {
this.key = key;
this.value = value;
}
// standard getters and setters
// standard equals and hashcode
// standard toString
}

Наконец, давайте посмотрим на несколько примеров использования:

Map.Entry<String, String> firstEntry = new SimpleCustomKeyValue<>("key1", "value1");

Map.Entry<String, String> secondEntry = new SimpleCustomKeyValue<>("key2", "value2");
secondEntry.setValue("different value");

Map<String, String> map = Map.ofEntries(firstEntry, secondEntry);

assertThat(map)
.isEqualTo(ImmutableMap.<String, String>builder()
.put("key1", "value1")
.put("key2", "different value")
.build());

5. Вывод

В этой статье мы узнали, как можно использовать существующие параметры, предоставляемые Java, и несколько альтернатив, предоставляемых некоторыми популярными сторонними библиотеками для создания экземпляра Entry . Кроме того, мы также создали пользовательскую реализацию и показали несколько примеров использования.

Как всегда, код этих примеров доступен на GitHub .