Java Stream 分组操作示例
一、Stream分组求和
使用 Collectors.groupingBy
和 Collectors.summingDouble
对 List 进行分组后求和。
/**
* 求和
*/
public void sum(){
List<Data> dataList = getDataList();
Map<String, Double> map = dataList.stream()
.collect(Collectors.groupingBy(Data::getType, Collectors.summingDouble(Data::getValue)));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1),
new Data("B", 2),
new Data("A", 3),
new Data("B", 4),
new Data("C", 5)
);
结果:
Map<String, Double> result = {
"A": 4.0,
"B": 6.0,
"C": 5.0
}
二、Stream分组前十
使用 Collectors.groupingBy
和 Stream.sorted().limit()
获取每组的前10个数据。
/**
* 分组前十
*/
public void top(){
List<Data> dataList = getDataList();
Map<String, List<Data>> groups = dataList.stream()
.collect(Collectors.groupingBy(Data::getType));
Map<String, List<Data>> result = new HashMap<>();
groups.forEach((k, v) -> {
List<Data> top = v.stream()
.sorted(Comparator.comparing(Data::getValue).reversed())
.limit(10)
.collect(Collectors.toList());
result.put(k, top);
});
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1),
new Data("B", 2),
new Data("A", 3),
new Data("B", 4),
new Data("C", 5)
);
结果:
Map<String, List<Data>> result = {
"A": [{type: "A", value: 3}, {type: "A", value: 1}],
"B": [{type: "B", value: 4}, {type: "B", value: 2}],
"C": [{type: "C", value: 5}]
}
三、Stream分组拼接
使用 Collectors.groupingBy
和 Collectors.mapping
+ Collectors.joining
对分组后的属性进行拼接。
/**
* 字符串拼接
*/
public void join(){
List<Data> dataList = getDataList();
Map<String, String> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType,
Collectors.mapping(Data::getName, Collectors.joining(","))));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1, "A1"),
new Data("B", 2, "B1"),
new Data("A", 3, "A2"),
new Data("B", 4, "B2"),
new Data("C", 5, "C1")
);
结果:
Map<String, String> result = {
"A": "A1,A2",
"B": "B1,B2",
"C": "C1"
}
四、Map转List Stream
使用 flatMap
将 Map 转换为 List,并在转换过程中添加额外属性。
/**
* Map转List
*/
public void mapToList(){
Map<String, List<Data>> map = getMap();
List<Data> result = map.entrySet()
.stream()
.flatMap(entry -> entry.getValue().stream()
.peek(data -> data.setType(entry.getKey())))
.collect(Collectors.toList());
}
示例数据:
Map<String, List<Data>> map = {
"A": [{value: 1}, {value: 2}],
"B": [{value: 3}, {value: 4}]
}
结果:
List<Data> result = [
{type: "A", value: 1},
{type: "A", value: 2},
{type: "B", value: 3},
{type: "B", value: 4}
]
五、Stream分组List
使用 Collectors.groupingBy
对 List 进行分组,返回分组后的 List。
/**
* 分组List
*/
public void groupList(){
List<Data> dataList = getDataList();
Map<String, List<Data>> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1),
new Data("B", 2),
new Data("A", 3),
new Data("B", 4),
new Data("C", 5)
);
结果:
Map<String, List<Data>> result = {
"A": [{type: "A", value: 1}, {type: "A", value: 3}],
"B": [{type: "B", value: 2}, {type: "B", value: 4}],
"C": [{type: "C", value: 5}]
}
六、Stream分组并排序
使用 Collectors.collectingAndThen
对分组后的 List 进行排序。
/**
* 分组排序
*/
public void sort(){
List<Data> dataList = getDataList();
Map<String, List<Data>> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType,
Collectors.collectingAndThen(Collectors.toList(), list -> {
list.sort(Comparator.comparingDouble(Data::getValue));
return list;
})));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1),
new Data("B", 2),
new Data("A", 3),
new Data("B", 4),
new Data("C", 5)
);
结果:
Map<String, List<Data>> result = {
"A": [{type: "A", value: 1}, {type: "A", value: 3}],
"B": [{type: "B", value: 2}, {type: "B", value: 4}],
"C": [{type: "C", value: 5}]
}
七、Stream分组计数
使用 Collectors.counting()
对每组数据进行计数。
/**
* 统计数量
*/
public void count(){
List<Data> dataList = getDataList();
Map<String, Long> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType, Collectors.counting()));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1),
new Data("B", 2),
new Data("A", 3),
new Data("B", 4),
new Data("C", 5)
);
结果:
Map<String, Long> result = {
"A": 2,
"B": 2,
"C": 1
}
八、Stream分组统计数量(带求和)
使用 Collectors.summingInt
对每组数据的数量属性进行求和。
/**
* 统计数量
*/
public void count(){
List<Data> dataList = getDataList();
Map<String, Integer> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType,
Collectors.summingInt(Data::getValue)));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1),
new Data("B", 2),
new Data("A", 3),
new Data("B", 4),
new Data("C", 5)
);
结果:
Map<String, Integer> result = {
"A": 4,
"B": 6,
"C": 5
}
九、Stream分组求和BigDecimal
使用 Collectors.reducing
对 BigDecimal 类型进行求和。
/**
* BigDecimal求和
*/
public void bigDecimalSumming(){
List<Data> dataList = getDataList();
Map<String, BigDecimal> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType,
Collectors.mapping(Data::getValue,
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", new BigDecimal(1)),
new Data("B", new BigDecimal(2)),
new Data("A", new BigDecimal(3)),
new Data("B", new BigDecimal(4)),
new Data("C", new BigDecimal(5))
);
结果:
Map<String, BigDecimal> result = {
"A": new BigDecimal(4),
"B": new BigDecimal(6),
"C": new BigDecimal(5)
}
十、Stream分组后对List处理选取
使用 Collectors.collectingAndThen
对分组后的 List 进行随机选取。
/**
* 分组取值
*/
public void groupSample(){
List<Data> dataList = getDataList();
int size = 2;
Map<String, List<String>> result = dataList.stream()
.collect(Collectors.groupingBy(Data::getType,
Collectors.collectingAndThen(Collectors.toList(), list -> {
Collections.shuffle(list);
return list.stream()
.limit(size)
.map(Data::getName)
.collect(Collectors.toList());
})));
}
示例数据:
List<Data> dataList = Arrays.asList(
new Data("A", 1, "A1"),
new Data("B", 2, "B1"),
new Data("A", 3, "A2"),
new Data("B", 4, "B2"),
new Data("C", 5)
);
结果:
Map<String, List<String>> result = {
"A": ["A2", "A1"],
"B": ["B2", "B1"],
"C": ["C1"]
}