Functional
Collectors.toMap: 重複キーにはmerge規則が必要
toMapは同じキーを見つけると、merge関数を指定していない限り例外にします。
SourceDuplicateKeys.java
Java 21
package examples.collector;
import java.util.List;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
public final class DuplicateKeys {
private DuplicateKeys() {}
public static Map<String, Integer> withoutMerge(List<String> values) {
return values.stream().collect(Collectors.toMap(String::toLowerCase, String::length));
}
public static Map<String, Integer> keepingLast(List<String> values) {
return values.stream()
.collect(Collectors.toMap(String::toLowerCase, String::length, BinaryOperator.maxBy(Integer::compare)));
}
}TestDuplicateKeysTest.java
Java 21
package examples.collector;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.List;
import org.junit.jupiter.api.Test;
class DuplicateKeysTest {
@Test
void toMapは同じキーがあるとmerge関数なしでは例外にする() {
assertThrows(
IllegalStateException.class, () -> DuplicateKeys.withoutMerge(List.of("Java", "JAVA")));
}
@Test
void merge関数を指定すると重複キーの扱いを明示できる() {
assertEquals(4, DuplicateKeys.keepingLast(List.of("Java", "JAVA")).get("java"));
}
}01Assertion
このテストで確認できること
- 同じキーが2回出るとIllegalStateExceptionになる
- merge関数で重複時の値選択を明示できる
入力が一意だという前提を暗黙にしないため、キーの重複可能性を確認し、必要ならmerge規則をコードに書きます。
OBSERVED RESULT
expected exception: duplicate key → IllegalStateException
merge result: java → 4