1.Collectors.groupingBy、Collectors.mapping:
参考博客:https://blog.csdn.net/L_fly_J/article/details/120164362
Person.java:

package com.mayikt.entity; public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
测试代码:
package com.mayikt.stream; import com.mayikt.entity.Person; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class TestCollectorsMapping { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person("Ram", 30)); list.add(new Person("Shyam", 20)); list.add(new Person("Shiv", 20)); list.add(new Person("Mahesh", 30)); String nameByAge = list.stream().collect(Collectors.mapping(Person::getName, Collectors.joining(",", "[", "]"))); System.out.println(nameByAge); nameByAge = list.stream().map(person -> person.getName()).collect(Collectors.joining(",", "[", "]")); System.out.println(nameByAge); Map<Integer, String> nameByAgeMap = list.stream().collect( Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.joining(",", "[", "]")))); nameByAgeMap.forEach((k, v) -> System.out.println("Age:" + k + " Persons: " + v)); Map<Integer, List<String>> map2 = list.stream().collect( Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.toList()))); System.out.println(map2); } }
[Ram,Shyam,Shiv,Mahesh] [Ram,Shyam,Shiv,Mahesh] 可以发现达到相同的效果 Age:20 Persons: [Shyam,Shiv] Age:30 Persons: [Ram,Mahesh] 封装为Map后返回 {20=[Shyam, Shiv], 30=[Ram, Mahesh]}
2、Collectors.groupingBy的使用例子2:
查看代码
package com.mayikt.entity;
public class UserAuth {
public String channelId;
public String authType;
public UserAuth(String channelId, String authType) {
this.channelId = channelId;
this.authType = authType;
}
public String getChannelId() {
return channelId;
}
public String getAuthType() {
return authType;
}
@Override
public String toString() {
return "UserAuth{" +
"channelId='" + channelId + '\'' +
", authType='" + authType + '\'' +
'}';
}
}
测试类:
package com.mayikt.stream;
import com.mayikt.entity.UserAuth;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestCollectorsGroupBy {
/**
* 假如有用户认证,认证在渠道 + 认证方式上。
* 现在想把这些数据,按照authType分组作为map的key,将渠道归集成list作为map的value,怎么做?
* @param args
*/
public static void main(String[] args) {
List<UserAuth> list = new ArrayList<>();
list.add(new UserAuth("EIBS", "B"));
list.add(new UserAuth("EMBS", "B"));
list.add(new UserAuth("EIBS", "K"));
Map<String, List<String>> authChannelMap0 =
list.stream().collect(Collectors.groupingBy(UserAuth::getAuthType, Collectors.mapping(UserAuth::getChannelId, Collectors.toList())));
System.out.println(authChannelMap0);
Map<String, String> authChannelMap2 =
list.stream().collect(Collectors.groupingBy(UserAuth::getAuthType, Collectors.mapping(UserAuth::getChannelId, Collectors.joining(",", "[", "]"))));
System.out.println(authChannelMap2);
}
}
console:
{B=[EIBS, EMBS], K=[EIBS]}
{B=[EIBS,EMBS], K=[EIBS]}
3.Collectors.groupingBy的三个方法
参考博客: https://blog.csdn.net/HO1_K/article/details/127572093
Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream)
classifier:键映射:该方法的返回值是键值对的 键
mapFactory:无参构造函数提供返回类型:提供一个容器初始化方法,用于创建新的 Map容器 (使用该容器存放值对)。
downstream:值映射:通过聚合方法将同键下的结果聚合为指定类型,该方法返回的是键值对的 值。
代码示例:
Order:
查看代码
package com.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* @description com.model
* @author: chengyu
* @date: 2023-10-08 19:25
*/
@Getter
@Setter
@ToString
@AllArgsConstructor
public class Order {
/**
* 机构号
*/
private Long deptSeq;
/**
* 订单号
*/
private String orderNo;
/**
* 订单金额
*/
private String amount;
}
package com.test.lamdba;
import com.model.Order;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class TestGroupingBy {
/**
* 将订单列表按机构号分组
* groupingBy有三个方法
*/
public static void main(String[] args) {
List<Order> orderList = new ArrayList<>();
orderList.add(new Order(340000L, "orderNo_001", "10"));
orderList.add(new Order(340101L, "orderNo_002", "20"));
orderList.add(new Order(340309L, "orderNo_003", "5"));
orderList.add(new Order(340309L, "orderNo_004", "12"));
/**
* 将订单按照机构号分组
* groupingBy的一个参数的方法,mapFactory是使用HashMap的,所以无序 值默认是ArrayList
*/
Map<Long, List<Order>> orderMap1 = orderList.stream().collect(Collectors.groupingBy(Order::getDeptSeq));
orderMap1.forEach((k, v) -> System.out.println("deptSeq:" + k + " Orders: " + v));
/**
* 将订单按照机构号分组
* groupingBy的两个参数的方法,指定了downstream
*/
Map<Long, String> orderMap2 = orderList.stream().collect(Collectors.groupingBy(Order::getDeptSeq, Collectors.mapping(Order::getOrderNo, Collectors.joining(","))));
orderMap2.forEach((k, v) -> System.out.println("deptSeq:" + k + " Orders: " + v));
/**
* 将订单按照机构号分组,并且有序(原来list的顺序)
* groupingBy的三个参数的方法,指定了mapFactory和downstream
*/
Map<Long, List<Order>> orderMap3 = orderList.stream().collect(Collectors.groupingBy(Order::getDeptSeq, TreeMap::new, Collectors.toList()));
orderMap3.forEach((k, v) -> System.out.println("deptSeq:" + k + " Orders: " + v));
}
}
deptSeq:340309 Orders: [Order(deptSeq=340309, orderNo=orderNo_003, amount=5), Order(deptSeq=340309, orderNo=orderNo_004, amount=12)]
deptSeq:340101 Orders: [Order(deptSeq=340101, orderNo=orderNo_002, amount=20)]
deptSeq:340000 Orders: [Order(deptSeq=340000, orderNo=orderNo_001, amount=10)]
deptSeq:340309 Orders: orderNo_003,orderNo_004
deptSeq:340101 Orders: orderNo_002
deptSeq:340000 Orders: orderNo_001
deptSeq:340000 Orders: [Order(deptSeq=340000, orderNo=orderNo_001, amount=10)]
deptSeq:340101 Orders: [Order(deptSeq=340101, orderNo=orderNo_002, amount=20)]
deptSeq:340309 Orders: [Order(deptSeq=340309, orderNo=orderNo_003, amount=5), Order(deptSeq=340309, orderNo=orderNo_004, amount=12)]
tips:
1.保证分组后的有序性的话,也可以自定义容器类型为LinkedHashMap。
2.也可以根据键的值,生成不同的范围,这种范围类型的键多数情况下都是通过比较来生成的,常用于统计指标,如:
查看代码
// 根据两级范围 将学生划分及格不及格两类
Map<Boolean, List<Student>> customRangeKey = students.stream().collect(Collectors.groupingBy(student -> student.getScore() > 60));
// 根据多级范围 根据学生成绩来评分
Map<String, List<Student>> customMultiRangeKey = students.stream().collect(Collectors.groupingBy(student -> {
if (student.getScore() < 60) {
return "C";
} else if (student.getScore() < 80) {
return "B";
}
return "A";
}));
3.分组统计功能,Collectors.counting:计数
查看代码
// 计数
Map<String, Long> groupCount = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.counting()));
----