1. 概要

このチュートリアルでは、Javaの組み込みクラス、サードパーティライブラリ、およびカスタム実装を使用して、キーと値の関連付けを表すEntryオブジェクトを作成する方法について説明します。 マップ

2. Java組み込みクラスの使用

Javaは、MapEntryインターフェースに、Entryを作成するための2つの簡単な実装を提供します。 それらを見てみましょう。

2.1. AbstractMapSimpleEntryを使用する

SimpleEntry クラスは、AbstractMapクラスの静的にネストされたクラスです。 インスタンスを初期化するための2つの異なるコンストラクターを提供します。

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"));

ここでわかるように、コンストラクターの1つはキーと値を受け入れ、もう1つはEntryインスタンスを受け入れて新しいEntryインスタンスを初期化します。

2.2. AbstractMapSimpleImmutableEntryを使用する

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の Map インターフェイスに静的メソッドentry()があり、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 クラスは、3つの異なるコンストラクターを提供します。 最初のものはキーと値のペアを受け入れますが、2番目と3番目はそれぞれエントリKeyValueのパラメータタイプを受け入れます。

UnmodizableMapEntryクラスも同じように動作します。

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"));

ただし、その名前からわかるように、 UnmodizableMapEntryでは、初期化後に値を変更することもできません

3.2. GoogleGuavaライブラリを使用する

まず、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インスタンスを作成するためのいくつかのオプションを見てきました。 これらのクラスは、HashMapなどのMapインターフェイス実装の内部ロジックに準拠する必要があるように設計されています。 

これは、これに準拠している限り、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で.