java8中,Collectors.groupingBy 会用得比较多,对其常见用法做一个汇总
1,模拟数据
Item
import java.math.BigDecimal;
public class Item {
private String name;
private Integer quantity;
private BigDecimal price;
public Item(String name, int quantity, BigDecimal price) {
this.name = name;
this.quantity = quantity;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
数据
public static List<Item> initData(){
List<Item> items = Arrays.asList(new Item("apple", 20, new BigDecimal("4.99")),
new Item("apple", 30, new BigDecimal("7.99")),
new Item("apple", 10, new BigDecimal("9.99")),
new Item("banana", 30, new BigDecimal("2.99")),
new Item("banana", 20, new BigDecimal("6.99")),
new Item("orange", 50, new BigDecimal("3.99")),
new Item("orange", 20, new BigDecimal("8.99")),
new Item("watermelon", 200, new BigDecimal("2.99")),
new Item("watermelon", 100, new BigDecimal("5.99")),
new Item("kiwi fruit", 40, new BigDecimal("5.88")),
new Item("kiwi fruit", 20, new BigDecimal("8.88")));
return items;
}
2,用法
1,groupingBy
// 根据水果名称分组
private static void groupingBy(){
List<Item> items = initData();
Map<String, List<Item>> itemGroupBy = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName));
System.out.println(JSON.toJSONString(itemGroupBy));
}
结果:
{
"orange": [{
"name": "orange",
"price": 3.99,
"quantity": 50
}, {
"name": "orange",
"price": 8.99,
"quantity": 20
}],
"banana": [{
"name": "banana",
"price": 2.99,
"quantity": 30
}, {
"name": "banana",
"price": 6.99,
"quantity": 20
}],
"apple": [{
"name": "apple",
"price": 4.99,
"quantity": 20
}, {
"name": "apple",
"price": 7.99,
"quantity": 30
}, {
"name": "apple",
"price": 9.99,
"quantity": 10
}],
"kiwi fruit": [{
"name": "kiwi fruit",
"price": 5.88,
"quantity": 40
}, {
"name": "kiwi fruit",
"price": 8.88,
"quantity": 20
}],
"watermelon": [{
"name": "watermelon",
"price": 2.99,
"quantity": 200
}, {
"name": "watermelon",
"price": 5.99,
"quantity": 100
}]
}
2,groupingCounting
// 统计水果的种类
private static void groupingCounting(){
List<Item> items = initData();
Map<String, Long> itemGroupCount = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName, Collectors.counting()));
System.out.println(JSON.toJSONString(itemGroupCount));
}
结果
{
"orange": 2,
"banana": 2,
"apple": 3,
"kiwi fruit": 2,
"watermelon": 2
}
3,groupingSum
// 统计各水果的总数量
private static void groupingSum(){
List<Item> items = initData();
Map<String, Integer> itemGroupSum = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName,
Collectors.summingInt(Item::getQuantity)));
System.out.println(JSON.toJSONString(itemGroupSum));
}
结果
{
"orange": 70,
"banana": 50,
"apple": 60,
"kiwi fruit": 60,
"watermelon": 300
}
4,groupingMax
// 统计各水果中数量最多的那个
private static void groupingMax(){
List<Item> items = initData();
Map<String, Item> itemGroupMax = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName,
Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Item::getQuantity)), Optional::get)));
System.out.println(JSON.toJSONString(itemGroupMax));
Map<String, Item> itemGroupMaxMap = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.toMap(Item::getName, Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Item::getQuantity))));
System.out.println(JSON.toJSONString(itemGroupMaxMap));
}
结果
{
"orange": {
"name": "orange",
"price": 3.99,
"quantity": 50
},
"banana": {
"name": "banana",
"price": 2.99,
"quantity": 30
},
"apple": {
"name": "apple",
"price": 7.99,
"quantity": 30
},
"kiwi fruit": {
"name": "kiwi fruit",
"price": 5.88,
"quantity": 40
},
"watermelon": {
"name": "watermelon",
"price": 2.99,
"quantity": 200
}
}
Collectors.collectingAndThen 聚合后再操作
其参数:
collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)
5,grouping mapping
// 统计各水果的价格
private static void groupingSet(){
List<Item> items = initData();
Map<String, Set<BigDecimal>> itemGroupSet = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName,
Collectors.mapping(Item::getPrice, Collectors.toSet())));
System.out.println(JSON.toJSONString(itemGroupSet));
Map<String, List<BigDecimal>> itemGroupList = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName,
Collectors.mapping(Item::getPrice, Collectors.toList())));
System.out.println(JSON.toJSONString(itemGroupList));
}
结果
{
"orange": [3.99, 8.99],
"banana": [2.99, 6.99],
"apple": [7.99, 9.99, 4.99],
"kiwi fruit": [5.88, 8.88],
"watermelon": [2.99, 5.99]
}
6,groupingMap
// 统计各水果的数量对应价格
private static void groupingMap(){
List<Item> items = initData();
Map<String, Map<Integer, BigDecimal>> itemGroupMap = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName,
Collectors.toMap(Item::getQuantity, Item::getPrice, (x, y) -> x)));
System.out.println(JSON.toJSONString(itemGroupMap));
Map<String, Map<Integer, BigDecimal>> itemGroupMap2 = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName, Collectors
.collectingAndThen(Collectors.toMap(Item::getQuantity, Item::getPrice), v -> v)));
System.out.println(JSON.toJSONString(itemGroupMap2));
}
结果
{
"orange": {
50: 3.99,
20: 8.99
},
"banana": {
20: 6.99,
30: 2.99
},
"apple": {
20: 4.99,
10: 9.99,
30: 7.99
},
"kiwi fruit": {
20: 8.88,
40: 5.88
},
"watermelon": {
100: 5.99,
200: 2.99
}
}
第一种更为简便
7,groupingAvg
// 统计各水果的平均数量 int double long 三种类型
private static void groupingAvg(){
List<Item> items = initData();
Map<String, Double> itemGroupAvg = ListUtils.emptyIfNull(items).stream()
.collect(Collectors.groupingBy(Item::getName,
Collectors.averagingInt(Item::getQuantity)));
System.out.println(JSON.toJSONString(itemGroupAvg));
}
结果
{
"orange": 35.0,
"banana": 25.0,
"apple": 20.0,
"kiwi fruit": 30.0,
"watermelon": 150.0
}
总结:
常见使用聚合再进行map处理,用于匹配数据。了解Collectors.collectingAndThen的用法,聚合后再进行操作。写不来,就分两步写,先完成,再优化。