1概要


List

から

Map

への変換は一般的な作業です。このチュートリアルでは、これを行うためのいくつかの方法について説明します。


List

の各要素には、結果として生じる

Map

のキーとして使用される識別子があると仮定します。


2サンプルデータ構造

まず、要素をモデル化しましょう。

public class Animal {
    private int id;
    private String name;

   // constructor/getters/setters
}


id

フィールドはユニークなので、キーにすることができます。

伝統的な方法で変換を始めましょう。


3 Java 8

より前

明らかに、コアのJavaメソッドを使用して

List

を____Mapに変換できます。

public Map<Integer, Animal> convertListBeforeJava8(List<Animal> list) {
    Map<Integer, Animal> map = new HashMap<>();
    for (Animal animal : list) {
        map.put(animal.getId(), animal);
    }
    return map;
}

変換をテストしましょう。

@Test
public void whenConvertBeforeJava8__thenReturnMapWithTheSameElements() {
    Map<Integer, Animal> map = convertListService
      .convertListBeforeJava8(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}


4 Java 8

の場合

Java 8以降では、ストリームと

Collectors

を使って

List



Map

に変換できます。

 public Map<Integer, Animal> convertListAfterJava8(List<Animal> list) {
    Map<Integer, Animal> map = list.stream()
      .collect(Collectors.toMap(Animal::getId, animal -> animal));
    return map;
}

繰り返しますが、変換が正しく行われたことを確認しましょう。

@Test
public void whenConvertAfterJava8__thenReturnMapWithTheSameElements() {
    Map<Integer, Animal> map = convertListService.convertListAfterJava8(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}


5グアバ図書館の利用

コアJavaの他に、変換にサードパーティのライブラリを使用することができます。


5.1. Mavenの設定

まず、

pom.xml

に次の依存関係を追加する必要があります。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>23.6.1-jre</version>
</dependency>

このライブラリの最新版は、いつでも見つけることができます。[ここに]。


5.2.

Maps.uniqueIndex()


による変換

次に、

List



Map

に変換するために

Maps.uniqueIndex()

メソッドを使用しましょう。

public Map<Integer, Animal> convertListWithGuava(List<Animal> list) {
    Map<Integer, Animal> map = Maps
      .uniqueIndex(list, Animal::getId);
    return map;
}

最後に、変換をテストしましょう。

@Test
public void whenConvertWithGuava__thenReturnMapWithTheSameElements() {
    Map<Integer, Animal> map = convertListService
      .convertListWithGuava(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}


6. Apache Commons Libraryを使う

Apache Commonsライブラリの


__ methodで変換することもできます。


6.1. Mavenの設定

まず、Mavenの依存関係を含めましょう。

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

この依存関係の最新版はhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22org.apache.commons%22%20AND%20a%3A%22commons-collections4%22にあります[ここに]。


6.2.

MapUtils


次に、

MapUtils.populateMap()

を使用して変換を行います。

public Map<Integer, Animal> convertListWithApacheCommons2(List<Animal> list) {
    Map<Integer, Animal> map = new HashMap<>();
    MapUtils.populateMap(map, list, Animal::getId);
    return map;
}

最後に、期待通りに動作することを確認しましょう。

@Test
public void whenConvertWithApacheCommons2__thenReturnMapWithTheSameElements() {
    Map<Integer, Animal> map = convertListService
      .convertListWithApacheCommons2(list);

    assertThat(
      map.values(),
      containsInAnyOrder(list.toArray()));
}


7. 値の衝突


id

フィールドが一意ではない場合にどうなるかを確認しましょう。


7.1.

Animals



List


重複した


id

__s

まず、一意ではない

__id


sを持つ


Animal


sの

List__を作成しましょう。

@Before
public void init() {

    this.duplicatedIdList = new ArrayList<>();

    Animal cat = new Animal(1, "Cat");
    duplicatedIdList.add(cat);
    Animal dog = new Animal(2, "Dog");
    duplicatedIdList.add(dog);
    Animal pig = new Animal(3, "Pig");
    duplicatedIdList.add(pig);
    Animal cow = new Animal(4, "Cow");
    duplicatedIdList.add(cow);
    Animal goat= new Animal(4, "Goat");
    duplicatedIdList.add(goat);
}

上記のように、

cow



goat

は同じ

id

を持ちます。


7.2. ふるまいをチェックする

  • Javaの

    Map

    s

    put()

    メソッドが実装されているため、最後に追加された値が前の値を同じキーで上書きします。

このため、従来の変換とApache Commons

MapUtils.populateMap()

は同じように動作します。

@Test
public void whenConvertBeforeJava8__thenReturnMapWithRewrittenElement() {

    Map<Integer, Animal> map = convertListService
      .convertListBeforeJava8(duplicatedIdList);

    assertThat(map.values(), hasSize(4));
    assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}

@Test
public void whenConvertWithApacheCommons__thenReturnMapWithRewrittenElement() {

    Map<Integer, Animal> map = convertListService
      .convertListWithApacheCommons(duplicatedIdList);

    assertThat(map.values(), hasSize(4));
    assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}

見てわかるように、

goat



cow

を同じ

id

で上書きします。

それとは異なり、**

Collectors.toMap()



MapUtils.populateMap()

はそれぞれ

IllegalStateException



IllegalArgumentException

をスローします。

@Test(expected = IllegalStateException.class)
public void givenADupIdList__whenConvertAfterJava8__thenException() {

    convertListService.convertListAfterJava8(duplicatedIdList);
}

@Test(expected = IllegalArgumentException.class)
public void givenADupIdList__whenConvertWithGuava__thenException() {

    convertListService.convertListWithGuava(duplicatedIdList);
}


8結論

このクイック記事では、

List

を____Mapに変換するさまざまな方法、コアJavaおよびいくつかの一般的なサードパーティ製ライブラリを使った例を提供しました。

いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/java-collections-conversions[GitHubで利用可能]です。