背景:希望List 可以根据某个字段 进行分组 然后拆分
使用Java 8 的流来做。
java.util.stream.Collectors#groupingBy(java.util.function.Function super T,? extends K>, java.util.stream.Collector super T,A,D>)
使用Group By 方法 默认会转换为 List
可以看到 默认是使用toList()
classifer 是返回的Map的Key 。
groupingBy(Function super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
public static
Collector> groupingBy(Function super T, ? extends K> classifier,
Collector super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}
这个可以提供转换的downStream,变成希望的类型。
public static >
Collector groupingBy(Function super T, ? extends K> classifier,
Supplier mapFactory,
Collector super T, A, D> downstream)
好了 来几个例子吧:
TestPerson 类, List 存储的是这个对象
private static classTestPerson {
String userName;intid;intage;public TestPerson(String userName, int id, intage) {this.userName =userName;this.id =id;this.age =age;
}publicString getUserName() {returnuserName;
}public voidsetUserName(String userName) {this.userName =userName;
}public intgetId() {returnid;
}public void setId(intid) {this.id =id;
}public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}
@OverridepublicString toString() {return "TestPerson{" +
"userName='" + userName + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
}
List 中 存储一些对象
List persons = Arrays.asList(
new TestPerson("zhangsan",1,20),
new TestPerson("lisi",2,21),
new TestPerson("wangwu",3,20)
);
案例1 :根据Age 分组,并且拆分成两个group
Map> personPerAge = persons.stream().collect(groupingBy(TestPerson::getAge));
System.out.println("分成了"+personPerAge.size()+"组");
for(List personList : personPerAge.values()) {
System.out.println("One group:");
for(TestPerson person :personList){
System.out.println(person);
}
}
console:
分成了 2组
One group:
TestPerson{userName='zhangsan', id=1, age=20}
TestPerson{userName='wangwu', id=3, age=20}
One group:
TestPerson{userName='lisi', id=2, age=21}
案例2 : 根据一个对象进行分组,
假设每个人都有个班级或者等级吧 , 这个时候我希望 同时加上这个班级的名称 进行分组
private static classTestClass{privateTestPerson person;privateString className;publicTestPerson getPerson() {returnperson;
}public voidsetPerson(TestPerson person) {this.person =person;
}publicString getClassName() {returnclassName;
}public voidsetClassName(String className) {this.className =className;
}
}
案例3 可以拿到每组中的最大值,平均值,最小值等等 ,是不是和数据库很像?
public static voidmain(String[] args) {
TestPerson zhangsan= new TestPerson("zhangsan",1,18);
TestPerson lisi= new TestPerson("lisi", 1, 19);
TestPerson wangwu= new TestPerson("wangwu", 2, 20);
TestPerson wangwu1= new TestPerson("wangwu1", 2, 21);/*List classes = Arrays.asList(
new TestClass(zhangsan,"A"),
new TestClass(zhangsan,"B"),
new TestClass(wangwu,"C")
);
Map> classPerPerson = classes.stream().collect(groupingBy(TestClass :: getPerson));
System.out.println("分成了"+classPerPerson.size()+"组");
for(List classList : classPerPerson.values()) {
System.out.println("One group:");
for(TestClass clazz : classList){
System.out.println(clazz);
}
}*/List persons =Arrays.asList(
zhangsan,
lisi,
wangwu,
wangwu1
);
Map personPerAge =persons.stream().collect(groupingBy(TestPerson::getId, summarizingInt(TestPerson::getAge)));
personPerAge.forEach((k,v)->
System.out.println("This group id is "+k+" and the summary is " +v)
);
}
对 后面我使用了forEach 和Lamda 表达式 一起配合使用,
当然 还支持过滤功能 ,大家可以一起来玩哈。
参考文章:
https://www.baeldung.com/java-groupingby-collector
https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html