1. 概要

このクイックチュートリアルでは、 MultiValuedMap ApacheCommonsCollectionsライブラリで提供されるインターフェース 。 

MultiValuedMapは、各キーをJavaの値のコレクションにマッピングするためのシンプルなAPIを提供します。 後継者です org.apache.commons.collections4.MultiMap、 CommonsCollection4.1で非推奨になりました。

2. Mavenの依存関係

Mavenプロジェクトの場合、commons-collections4依存関係を追加する必要があります。

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

3. MultiValuedMapへの要素の追加

putおよびputAllメソッドを使用して要素を追加できます。

MultiValuedMapのインスタンスを作成することから始めましょう。

MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>();

次に、putメソッドを使用して要素を一度に1つずつ追加する方法を見てみましょう。

map.put("fruits", "apple");
map.put("fruits", "orange");

さらに、 putAll メソッドを使用していくつかの要素を追加しましょう。このメソッドは、1回の呼び出しでキーを複数の要素にマップします。

map.putAll("vehicles", Arrays.asList("car", "bike"));
assertThat((Collection<String>) map.get("vehicles"))
  .containsExactly("car", "bike");

4. MultiValuedMapからの要素の取得

MultiValuedMap は、キー、値、およびキーと値のマッピングを取得するためのメソッドを提供します。 それらのそれぞれを見てみましょう。

4.1. キーのすべての値を取得する

キーに関連付けられているすべての値を取得するには、 get メソッドを使用して、Collectionを返します。

assertThat((Collection<String>) map.get("fruits"))
  .containsExactly("apple", "orange");

4.2. すべてのキー値マッピングを取得

または、 items メソッドを使用して、マップに含まれるすべてのキー値マッピングのCollectionを取得できます。

Collection<Map.Entry<String, String>> entries = map.entries();

4.3. すべてのキーを取得

MultiValuedMap。に含まれるすべてのキーを取得するには2つの方法があります。

keys メソッドを使用して、キーのMultiSetビューを取得してみましょう。

MultiSet<String> keys = map.keys();
assertThat(keys).contains("fruits", "vehicles");

または、 keySet メソッドを使用して、キーのSetビューを取得することもできます。

Set<String> keys = map.keySet();
assertThat(keys).contains("fruits", "vehicles");

4.4. マップのすべての値を取得する

最後に、マップに含まれるすべての値の Collection ビューを取得する場合は、メソッドを使用できます。

Collection<String> values = map.values();
assertThat(values).contains("apple", "orange", "car", "bike");

5. MultiValuedMapからの要素の削除

それでは、要素とキーと値のマッピングを削除するためのすべての方法を見てみましょう。

5.1. キーにマップされているすべての要素を削除します

まず、 remove メソッドを使用して、指定されたキーに関連付けられているすべての値を削除する方法を見てみましょう。

Collection<String> removedValues = map.remove("fruits");
assertThat(map.containsKey("fruits")).isFalse();
assertThat(removedValues).contains("apple", "orange");

このメソッドは、削除された値のCollectionビューを返します。

5.2. 単一のキーと値のマッピングを削除する

ここで、キーが複数の値にマップされているが、マップされた値の1つだけを削除し、他の値は残したいとします。 これは、removeMappingメソッドを使用して簡単に行うことができます。

boolean isRemoved = map.removeMapping("fruits","apple");
assertThat(map.containsMapping("fruits","apple")).isFalse();

5.3. すべてのキー値マッピングを削除する

そして最後に、 clear メソッドを使用して、マップからすべてのマッピングを削除できます。

map.clear();
assertThat(map.isEmpty()).isTrue();

6. チェック中 MultiValuedMapの要素

次に、指定されたキーまたは値がマップに存在するかどうかを確認するためのさまざまな方法を見てみましょう。

6.1. キーが存在するかどうかを確認します

マップに指定されたキーのマッピングが含まれているかどうかを確認するには、containsKeyメソッドを使用できます。

assertThat(map.containsKey("vehicles")).isTrue();

6.2. 値が存在するかどうかを確認します

次に、マップ内の少なくとも1つのキーに特定の値のマッピングが含まれているかどうかを確認するとします。 これは、containsValueメソッドを使用して実行できます。

assertThat(map.containsValue("orange")).isTrue();

6.3. キー値マッピングが存在するかどうかを確認します

同様に、マップに特定のキーと値のペアのマッピングが含まれているかどうかを確認する場合は、containsMappingメソッドを使用できます。

assertThat(map.containsMapping("fruits","orange")).isTrue();

6.4. マップが空かどうかを確認する

マップにキーと値のマッピングがまったく含まれていないかどうかを確認するには、isEmptyメソッドを使用できます。

assertThat(map.isEmpty()).isFalse;

6.5. マップのサイズを確認してください

最後に、 size メソッドを使用して、マップの合計サイズを取得できます。 マップに複数の値を持つキーがある場合、マップの合計サイズは、すべてのキーからのすべての値のカウントです。

assertEquals(4, map.size());

7. 実装

Apache Commons Collections Libraryは、このインターフェースの複数の実装も提供します。 それらを見てみましょう。

7.1. ArrayListValuedHashMap

ArrayListValuedHashMap は、各キーに関連付けられた値を格納するために ArrayList を内部的に使用するため、キーと値のペアの重複を許可します

MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "orange");
map.put("fruits", "orange");
assertThat((Collection<String>) map.get("fruits"))
  .containsExactly("apple", "orange", "orange");

ここで、このクラスはスレッドセーフではないことに注意してください。 したがって、このマップを複数のスレッドから使用する場合は、適切な同期を使用する必要があります。

7.2. HashSetValuedHashMap

HashSetValuedHashMap は、 HashSet を使用して、指定された各キーの値を格納します。 したがって、キーと値のペアの重複は許可されません

同じKey-Valueマッピングを2回追加する簡単な例を見てみましょう。

MultiValuedMap<String, String> map = new HashSetValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "apple");
assertThat((Collection<String>) map.get("fruits"))
  .containsExactly("apple");

ArrayListValuedHashMapを使用した前の例とは異なり、 HashSetValuedHashMap実装は重複するマッピングを無視することに注意してください。

HashSetValuedHashMapクラスもスレッドセーフではありません

7.3. UnmodizableMultiValuedMap

UnmodizableMultiValuedMap は、 MultiValuedMap の不変インスタンスが必要な場合に役立つデコレータクラスです。つまり、それ以上の変更は許可されません。

@Test(expected = UnsupportedOperationException.class)
public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() {
    MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>();
    map.put("fruits", "apple");
    map.put("fruits", "orange");
    MultiValuedMap<String, String> immutableMap =
      MultiMapUtils.unmodifiableMultiValuedMap(map);
    immutableMap.put("fruits", "banana"); // throws exception
}

また、の最終プットを変更すると、UnsupportedOperationExceptionが発生することに注意してください。

8. 結論

ApacheCommonsCollectionsライブラリのMultiValuedMapインターフェースのさまざまなメソッドを見てきました。 さらに、いくつかの一般的な実装についても説明しました。

そして、いつものように、完全なソースコードはGithub利用できます。