Java 8でCollectionをMapに変換する方法
9207 ワード
Java 8のjava.util.stream.Collectorsでは、CollectionをMap構造に変換するためのいくつかの方法が提供されています.この文書では、3つの個人的な理解を記録します.
Method
Return Type
groupingBy
partitioningBy
toMap
1.環境
Java: jdk1.8.0_144
2.特性説明
Student.java
fakeStudent()メソッド
2.1. Collectors.groupingBy
a)Functionの戻り値で集合をグループ化し,それをKeyとし,対応するリストをValueとし,Mapを返す.
b)Key対応リストが空の場合、返されるMapにはそのKeyが含まれない
c)Functionの戻り値がNullの場合、Null PointerExceptionを投げ出す
2.2. Collectors.partitioningBy
a)Predicateの戻り値によって集合を2つのグループに分け,適合条件のリストはtrueをKey,適合しないリストはfalseをKeyとする.
b)Predicateの戻り値がNullの場合、Null PointerExceptionを投げ出す
2.3. Collectors.toMap
a)keyMapperのFunction戻り値をKey、valueMapperのFunction戻り値をValueとしてMapを形成する
b)KeyがNullであれば、正しく戻ることができる
c)Key値が重複する場合、デフォルトでIllegalStateExceptionを放出 toMapの競合ポリシーを決定します.たとえば、前者の を指定します. toMapメソッドを放棄しcollect を利用する
d)ValueがNullであればNull PointerExceptionを投げ出す
3.結語 Collectors.groupingBy/Collectors.partitioningByの中心思想はすべて元の集合を何らかの条件でグループ化し、グループ化条件はNullではない.ただし、Collectors.partitioningByのパケット条件は、断言であり、true/falseに対応する2つの値のセットを永遠に返します.これらの値は、Valueが空のリストである可能性がありますが、Collectors.groupingByのパケット結果が空のリストである場合、 が破棄されます. Collectors.toMapはCollectors.groupingBy/Collectors.partitioningByとは異なり、集合内の要素を何らかの形で1つのMapに分解するだけであり、このMapのkeyはNullであっても重複は許されないが、MapのValueはNull であってはならない.
4.参考資料コードアドレスhttps://github.com/hivsuper/study/blob/master/study-java8/src/test/java/org/lxp/java8/map/CollectionToMapTest.java https://stackoverflow.com/questions/27993604/whats-the-purpose-of-partitioningby
転載先:https://www.cnblogs.com/hiver/p/9156147.html
Method
Return Type
groupingBy
Map>
partitioningBy
Map>
toMap
Map
1.環境
Java: jdk1.8.0_144
2.特性説明
Student.java
public class Student {
private String studentNo;
private String name;
private Boolean gender;
private int age;
public Student(String studentNo, String name, Boolean gender, int age) {
this.studentNo = studentNo;
this.name = name;
this.gender = gender;
this.age = age;
}
public String getStudentNo() {
return studentNo;
}
public String getName() {
return name;
}
public Boolean getGender() {
return gender;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return String.format("Student [studentNo=%s, name=%s, gender=%s, age=%s]", studentNo, name, gender, age);
}
}
fakeStudent()メソッド
private List fakeStudent() {
List students = new ArrayList<>();
students.add(new Student("1", "name1", false, 2));
students.add(new Student("2", "name2", false, 2));
students.add(new Student("3", "name2", null, 2));
students.add(new Student("4", "name4", true, 2));
students.add(new Student(null, "name5", true, 2));
return students;
}
2.1. Collectors.groupingBy
public static Collector>> groupingBy(Function super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
a)Functionの戻り値で集合をグループ化し,それをKeyとし,対応するリストをValueとし,Mapを返す.
b)Key対応リストが空の場合、返されるMapにはそのKeyが含まれない
c)Functionの戻り値がNullの場合、Null PointerExceptionを投げ出す
@Test(expected = NullPointerException.class)
public void shouldThrowNPEWhenGroupingByNullKey() {
fakeStudent().stream().collect(Collectors.groupingBy(Student::getStudentNo));
}
2.2. Collectors.partitioningBy
public static Collector>> partitioningBy(Predicate super T> predicate) {
return partitioningBy(predicate, toList());
}
a)Predicateの戻り値によって集合を2つのグループに分け,適合条件のリストはtrueをKey,適合しないリストはfalseをKeyとする.
b)Predicateの戻り値がNullの場合、Null PointerExceptionを投げ出す
@Test(expected = NullPointerException.class)
public void shouldReturnMapWhenPartitioningByNullKey() {
fakeStudent().stream().collect(Collectors.partitioningBy(Student::getGender));
}
2.3. Collectors.toMap
public static Collector> toMap(Function super T, ? extends K> keyMapper, Function super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
a)keyMapperのFunction戻り値をKey、valueMapperのFunction戻り値をValueとしてMapを形成する
b)KeyがNullであれば、正しく戻ることができる
@Test
public void shouldReturnMapWhenToMapNullKey() {
Map map = fakeStudent().stream()
.collect(Collectors.toMap(Student::getStudentNo, Function.identity()));
assertEquals("{null=Student [studentNo=null, name=name5, gender=true, age=2], "
+ "1=Student [studentNo=1, name=name1, gender=false, age=2], "
+ "2=Student [studentNo=2, name=name2, gender=false, age=2], "
+ "3=Student [studentNo=3, name=name2, gender=null, age=2], "
+ "4=Student [studentNo=4, name=name4, gender=true, age=2]}", map.toString());
}
c)Key値が重複する場合、デフォルトでIllegalStateExceptionを放出
@Test
public void shouldThrowIllegalStateExceptionWhenToMapDuplicateKey() {
Map map = null;
try {
map = fakeStudent().stream().collect(Collectors.toMap(Student::getName, Function.identity()));
} catch (Exception e) {
assertTrue(e instanceof IllegalStateException);
assertEquals("Duplicate key Student [studentNo=2, name=name2, gender=false, age=2]", e.getMessage());
}
assertNull(map);
}
Duplicate Key
の問題を回避する必要がある場合は、2つの選択肢があります.@Test
public void shouldReturnMapWhenToMapDuplicateKey() {
Map map = fakeStudent().stream()
.collect(Collectors.toMap(Student::getName, Function.identity(), (student1, student2) -> student1));
assertEquals("{name5=Student [studentNo=null, name=name5, gender=true, age=2], "
+ "name4=Student [studentNo=4, name=name4, gender=true, age=2], "
+ "name2=Student [studentNo=2, name=name2, gender=false, age=2], "
+ "name1=Student [studentNo=1, name=name1, gender=false, age=2]}", map.toString());
}
@Test
public void shouldReturnMapWhenCollectDuplicateKey() {
Map map = fakeStudent().stream().collect(HashMap::new, (m, v) -> m.put(v.getName(), v),
HashMap::putAll);
assertEquals("{name5=Student [studentNo=null, name=name5, gender=true, age=2], "
+ "name4=Student [studentNo=4, name=name4, gender=true, age=2], "
+ "name2=Student [studentNo=3, name=name2, gender=null, age=2], "
+ "name1=Student [studentNo=1, name=name1, gender=false, age=2]}", map.toString());
}
d)ValueがNullであればNull PointerExceptionを投げ出す
@Test(expected = NullPointerException.class)
public void shouldThrowNPEWhenToMapNullValue() {
fakeStudent().stream().collect(Collectors.toMap(Student::getStudentNo, Student::getGender));
}
3.結語
@Test
public void shouldReturnSameMapWhenGroupingByAndPartitioningBy() {
List students = fakeStudent().stream().filter(student -> student.getGender() != null)
.collect(Collectors.toList());
Map> groupingByMap = students.stream()
.collect(Collectors.groupingBy(Student::getGender));
Map> partitioningByMap = students.stream()
.collect(Collectors.partitioningBy(Student::getGender));
assertEquals("{false=[Student [studentNo=1, name=name1, gender=false, age=2], "
+ "Student [studentNo=2, name=name2, gender=false, age=2]], "
+ "true=[Student [studentNo=4, name=name4, gender=true, age=2], "
+ "Student [studentNo=null, name=name5, gender=true, age=2]]}", groupingByMap.toString());
assertEquals(groupingByMap.toString(), partitioningByMap.toString());
}
@Test
public void shouldReturnDifferentMapWhenGroupingByAndPartitioningBy() {
Function function = student -> student.getAge() > 3;
List students = fakeStudent();
Map> groupingByMap = students.stream().collect(Collectors.groupingBy(function));
Map> partitioningByMap = students.stream()
.collect(Collectors.partitioningBy(function::apply));
assertEquals("{false=[Student [studentNo=1, name=name1, gender=false, age=2], "
+ "Student [studentNo=2, name=name2, gender=false, age=2], "
+ "Student [studentNo=3, name=name2, gender=null, age=2], "
+ "Student [studentNo=4, name=name4, gender=true, age=2], "
+ "Student [studentNo=null, name=name5, gender=true, age=2]]}", groupingByMap.toString());
assertEquals(
"{false=[Student [studentNo=1, name=name1, gender=false, age=2], "
+ "Student [studentNo=2, name=name2, gender=false, age=2], "
+ "Student [studentNo=3, name=name2, gender=null, age=2], "
+ "Student [studentNo=4, name=name4, gender=true, age=2], "
+ "Student [studentNo=null, name=name5, gender=true, age=2]], true=[]}",
partitioningByMap.toString());
}
4.参考資料
転載先:https://www.cnblogs.com/hiver/p/9156147.html