Java中的Collectors类的groupingBy()方法用于按某些属性对对象进行分组并将结果存储在Map实例中。

当我我们想利用它的特性,我们需要指定一个属性来执行分组。此方法提供的函数类似于SQL的GROUP BY子句。

用法:

public static Collector<T, ?, Map<K, List>> groupingBy(Function classifier)

类型参数:此方法采用两个类型参数:

T-这是输入元素的类型。

K-这是要转换的输入元素的类型。

参数:此方法接受两个强制性参数:

Function-这是要应用于输入元素的属性。

Classifier-它用于将输入元素映射到目标映射中。

返回值:它返回一个Collector作为Map。

Collectors.groupingBy根据一个或多个属性对集合中的项目进行分组

1、测试数据准备

1.1、首先,创建一个实体生产实体类,用于模拟测试数据

@Data
public class Product {
private Long id;
private Integer num;
private BigDecimal price;
private String name;
private String category;
private Integer size; public Product(Long id, Integer num, BigDecimal price, String name, String category, Integer size) {
this.id = id;
this.num = num;
this.price = price;
this.name = name;
this.category = category;
this.size = size;
}
}

1.2、创建测试类

代码结构如下:

构造测试数据:

  Product prod1 = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食",1);
Product prod2 = new Product(2L, 2, new BigDecimal("20"), "饼干", "零食",1);
Product prod3 = new Product(3L, 3, new BigDecimal("30"), "月饼", "零食",2);
Product prod4 = new Product(4L, 3, new BigDecimal("10"), "青岛啤酒", "啤酒",1);
Product prod5 = new Product(5L, 10, new BigDecimal("15"), "百威啤酒", "啤酒",1);
Product prod6 = new Product(6L, 7, new BigDecimal("25"), "百威啤酒", "啤酒",1);
Product prod7 = new Product(7L, 1, new BigDecimal("15.4"), "面包", "零食",1);
Product prod8 = new Product(8L, 7, new BigDecimal("25.5"), "百威啤酒", "啤酒",2);
List<Product> prodList = List.of(prod1, prod2, prod3, prod4, prod5, prod6,prod7,prod8);

2、开始测试

2.1、按照类别分组

    Map<String, List<Product>> map1 = prodList.stream().collect(Collectors.groupingBy(Product::getCategory));
Set<Map.Entry<String, List<Product>>> entries1 = map1.entrySet();
for (Map.Entry<String, List<Product>> entry : entries1) {
System.out.println(entry);
}

分组结果

==============================按照类别分组=============================================
啤酒=[Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒', size=1}, Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒', size=1}, Product{id=6, num=7, price=25, name='百威啤酒', category='啤酒', size=1}, Product{id=8, num=7, price=25.5, name='百威啤酒', category='啤酒', size=2}]
零食=[Product{id=1, num=1, price=15.5, name='面包', category='零食', size=1}, Product{id=2, num=2, price=20, name='饼干', category='零食', size=1}, Product{id=3, num=3, price=30, name='月饼', category='零食', size=2}, Product{id=7, num=1, price=15.4, name='面包', category='零食', size=1}]

2.2、按照多个属性拼接分组(类别+名称)

Map<String, List<Product>> map2 = prodList.stream()
.collect(Collectors.groupingBy(new Function<Product, String>() {
@Override
public String apply(Product product) {
return product.getCategory() + "_" + product.getName();
}
}
)
); Set<Map.Entry<String, List<Product>>> entries2 = map2.entrySet();
for (Map.Entry<String, List<Product>> entry : entries2) {
System.out.println(entry);
}

分组结果

==============================按照多个属性拼接分组(类别——名称)=============================================
零食_月饼=[Product{id=3, num=3, price=30, name='月饼', category='零食', size=2}]
零食_面包=[Product{id=1, num=1, price=15.5, name='面包', category='零食', size=1}, Product{id=7, num=1, price=15.4, name='面包', category='零食', size=1}]
啤酒_百威啤酒=[Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒', size=1}, Product{id=6, num=7, price=25, name='百威啤酒', category='啤酒', size=1}, Product{id=8, num=7, price=25.5, name='百威啤酒', category='啤酒', size=2}]
啤酒_青岛啤酒=[Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒', size=1}]
零食_饼干=[Product{id=2, num=2, price=20, name='饼干', category='零食', size=1}]

2.3、按照num数值的大小来

    Map<String, List<Product>> map3 = prodList.stream().collect(Collectors.groupingBy(item -> {
if (item.getNum() > 3) {
return "num大于3";
} else if (item.getNum() < 3) {
return "num小于3";
} else {
return "num等于3";
}
}));
Set<Map.Entry<String, List<Product>>> entries3 = map3.entrySet();
for (Map.Entry<String, List<Product>> entry : entries3) {
System.out.println(entry);
}

分组结果

===========================按照num数值的大小来================================================
num小于3=[Product{id=1, num=1, price=15.5, name='面包', category='零食', size=1}, Product{id=2, num=2, price=20, name='饼干', category='零食', size=1}, Product{id=7, num=1, price=15.4, name='面包', category='零食', size=1}]
num等于3=[Product{id=3, num=3, price=30, name='月饼', category='零食', size=2}, Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒', size=1}]
num大于3=[Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒', size=1}, Product{id=6, num=7, price=25, name='百威啤酒', category='啤酒', size=1}, Product{id=8, num=7, price=25.5, name='百威啤酒', category='啤酒', size=2}]

2.4、先按照类别分组,再按照num分组

 Map<String, Map<String, List<Product>>> map4 = prodList.stream()
.collect(Collectors.groupingBy(Product::getCategory, Collectors.groupingBy(item -> {
if (item.getNum() >= 8) {
return "num大于等于8";
} else {
return "num小于8";
}
})));
Set<Map.Entry<String, Map<String, List<Product>>>> entries4 = map4.entrySet();
for (Map.Entry<String, Map<String, List<Product>>> entry : entries4) {
System.out.println(entry);
}

分组结果

===========================先按照类别分组,再按照num分组================================================
啤酒={num小于8=[Product{id=4, num=3, price=10, name='青岛啤酒', category='啤酒', size=1}, Product{id=6, num=7, price=25, name='百威啤酒', category='啤酒', size=1}, Product{id=8, num=7, price=25.5, name='百威啤酒', category='啤酒', size=2}], num大于等于8=[Product{id=5, num=10, price=15, name='百威啤酒', category='啤酒', size=1}]}
零食={num小于8=[Product{id=1, num=1, price=15.5, name='面包', category='零食', size=1}, Product{id=2, num=2, price=20, name='饼干', category='零食', size=1}, Product{id=3, num=3, price=30, name='月饼', category='零食', size=2}, Product{id=7, num=1, price=15.4, name='面包', category='零食', size=1}]}

2.5、先按照类别分组,再聚合求总数

Map<String, Long> map5 = prodList.stream()
.collect(Collectors.groupingBy(Product::getCategory, Collectors.counting()));
Set<String> strings5 = map5.keySet();
for (String s : strings5) {
System.out.println(s + "---" + "总数:" + map5.get(s));
}

分组结果

===========================先按照类别分组,再聚合求总数================================================
啤酒---总数:4
零食---总数:4

2.6、先按照类别分组,再聚合运算(把num相加)

Map<String, Integer> map6 = prodList.stream()
.collect(Collectors.groupingBy(Product::getCategory, Collectors.summingInt(Product::getNum)));
Set<String> strings6 = map6.keySet();
for (String s : strings6) {
System.out.println(s + "---" + "num相加后:" + map6.get(s));
}

分组结果

===========================先按照类别分组,再聚合运算(把num相加)================================================
啤酒---num相加后:27
零食---num相加后:7

Java-Collectors.groupingBy的更多相关文章

  1. Java 8 – Stream Collectors groupingBy count examples

    Java 8 – Stream Collectors groupingBy count examples 1. Group By, Count and Sort1.1 Group by a List ...

  2. Collectors.groupingBy分组后的排序问题

    默认groupingBy代码里会生成一个HashMap(hashMap是无序的,put的顺序与get的顺序不一致) HashMap是无序的,HashMap在put的时候是根据key的hashcode进 ...

  3. [转]深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

    以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...

  4. Java基础系列-Collector和Collectors

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...

  5. 深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

    转载:http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/ 关于 深入理解 Java 8 Lambda(语言篇——l ...

  6. Java 8 - Stream Collectors分组的例子

    1.分组依据,计数和排序 1.1按a分组List并显示它的总数. package com.mkyong.java8; import java.util.Arrays; import java.util ...

  7. Java 8 Stream 的终极技巧——Collectors 操作

    1. 前言 昨天在 Collection移除元素操作 相关的文章中提到了 Collectors .相信很多同学对这个比较感兴趣,那我们今天就来研究一下 Collectors . 2. Collecto ...

  8. java stream中Collectors的用法

    目录 简介 Collectors.toList() Collectors.toSet() Collectors.toCollection() Collectors.toMap() Collectors ...

  9. 【Java 基础】Collectors 使用小结

    Collectors 与集合转换 Collectors toList streamArr.collect(Collectors.toList()); List<Integer> colle ...

  10. Java 8函数编程轻松入门(四)方法引用

    C#中系统提供了许多IEnumerable的扩展方法.同样在Java 8中新引入了Collector类. 1.方法引用 定义: 简而言之:就是一个Lambda表达式.在Java 8中,我们我们会使用L ...

随机推荐

  1. vue + element-ui + vue-clipboard2 实现文字复制粘贴功能与提示

    1.在所在项目下安装插件 npm install vue-clipboard2 --save 2.在所在项目的index.js注入vue-clipboard2 import VueClipboard ...

  2. windows C++

    #include <Windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar ...

  3. 2.11-12 滴水new-delete-vector(动态数组编写)

    去长沙玩了几天,没学 1.new 与 delete 通过调用分析了解到new在堆区开辟数据 delete就是释放数据 案例 #include<stdio.h> #include <m ...

  4. CF1638E Colorful Operations

    \(\text{Solution}\) \(\text{code}\) #include <cstdio> #include <iostream> #include <s ...

  5. JZOJ 4299. 【NOIP2015模拟11.2晚】舳舻牌

    题目 思路 倒序 \(DP\) 设 \(f_{i,j}\) 表示 \(A\) 先手,当前 \(A\) 报出的值为 \(i\),\(B\) 报出的值为 \(j\),\(A\) 取诱惑值大于等于 \(i\ ...

  6. Postgresql的csv日志设置

    PG的日志系统比较完善,除去系统启动时指定的日志,wal日志等外,下面主要介绍另一个详细的输出日志:csv log. 涉及到的参数文件:$PGDATA/postgresql.conf涉及的主要参数: ...

  7. element导航栏组件封装递归调用

    element导航栏组件封装递归调用: https://blog.csdn.net/qq_21271511/article/details/109889934

  8. 开源持续测试平台--MerterSphere

    一.MeterSphere平台介绍 MeterSphere是一站式的开源持续测试平台,遵循 GPL v3 开源许可协议,涵盖测试跟踪.接口测试.UI测试和性能测试等功能,全面兼容JMeter.Sele ...

  9. Visual Studio 2022 不支持 .NET Framework 老版本 项目解决办法

    Visual Studio 2022 不支持 .NET Framework老版本 (4.5) 项目解决办法 新电脑安装的是Visual Studio 2022,打开老项目的时候发现没有.net fra ...

  10. sql语句顺序/包含执行顺序和书写顺序

    分页查询 如果一页记录为10条,希望查看第3页记录应该怎么查呢?  第一页记录起始行为0,一共查询10行:  第二页记录起始行为10,一共查询10行:  第三页记录起始行为20,一共查询10行: ...