Javaでリストをマップに変換する方法
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で利用可能]です。