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

数据准备:

public Product(Long id, Integer num, BigDecimal price, String name, String category) {
	this.id = id;
	this.num = num;
	this.price = price;
	this.name = name;
	this.category = category;
Product prod1 = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食");
Product prod2 = new Product(2L, 2, new BigDecimal("20"), "饼干", "零食");
Product prod3 = new Product(3L, 3, new BigDecimal("30"), "月饼", "零食");
Product prod4 = new Product(4L, 3, new BigDecimal("10"), "青岛啤酒", "啤酒");
Product prod5 = new Product(5L, 10, new BigDecimal("15"), "百威啤酒", "啤酒");
List<Product> prodList = Lists.newArrayList(prod1, prod2, prod3, prod4, prod5);
  • 按照类目分组:
Map<String, List<Product>> prodMap= prodList.stream().collect(Collectors.groupingBy(Product::getCategory));
//{"啤酒":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],"零食":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},{"category":"零食","id":2,"name":"饼干","num":2,"price":20},{"category":"零食","id":3,"name":"月饼","num":3,"price":30}]}
  • 按照几个属性拼接分组:
Map<String, List<Product>> prodMap = prodList.stream().collect(Collectors.groupingBy(item -> item.getCategory() + "_" + item.getName()));
//{"零食_月饼":[{"category":"零食","id":3,"name":"月饼","num":3,"price":30}],"零食_面包":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5}],"啤酒_百威啤酒":[{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],"啤酒_青岛啤酒":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10}],"零食_饼干":[{"category":"零食","id":2,"name":"饼干","num":2,"price":20}]}
  • 根据不同条件分组
Map<String, List<Product>> prodMap= prodList.stream().collect(Collectors.groupingBy(item -> {
	if(item.getNum() < 3) {
		return "3";
	}else {
		return "other";
//{"other":[{"category":"零食","id":3,"name":"月饼","num":3,"price":30},{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}],"3":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},{"category":"零食","id":2,"name":"饼干","num":2,"price":20}]}

要实现多级分组,我们可以使用一个由双参数版本的Collectors.groupingBy工厂方法创 建的收集器,它除了普通的分类函数之外,还可以接受collector类型的第二个参数。那么要进 行二级分组的话,我们可以把一个内层groupingBy传递给外层groupingBy,并定义一个为流 中项目分类的二级标准。

Map<String, Map<String, List<Product>>> prodMap= prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.groupingBy(item -> {
	if(item.getNum() < 3) {
		return "3";
	}else {
		return "other";
})));
//{"啤酒":{"other":[{"category":"啤酒","id":4,"name":"青岛啤酒","num":3,"price":10},{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15}]},"零食":{"other":[{"category":"零食","id":3,"name":"月饼","num":3,"price":30}],"3":[{"category":"零食","id":1,"name":"面包","num":1,"price":15.5},{"category":"零食","id":2,"name":"饼干","num":2,"price":20}]}}

按子组收集数据

Map<String, Long> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.counting()));
//{"啤酒":2,"零食":3}
Map<String, Integer> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.summingInt(Product::getNum)));
//{"啤酒":13,"零食":6}
  • 把收集器的结果转换为另一种类型
Map<String, Product> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Product::getNum)), Optional::get)));
//{"啤酒":{"category":"啤酒","id":5,"name":"百威啤酒","num":10,"price":15},"零食":{"category":"零食","id":3,"name":"月饼","num":3,"price":30}}
  • 联合其他收集器
Map<String, Set<String>> prodMap = prodList.stream().collect(Collectors.groupingBy(Product::getCategory, Collectors.mapping(Product::getName, Collectors.toSet())));
//{"啤酒":["青岛啤酒","百威啤酒"],"零食":["面包","饼干","月饼"]}

相关链接:
java8中map新增方法详解
java8中Stream的使用
java8中Collection新增方法详解
java8中Collectors的方法使用实例
java8中常用函数式接口
java8中的方法引用和构造函数引用
java8中的Collectors.groupingBy用法
java8中的Optional用法
java8中的日期和时间API

比如说将有序的订单列表(按照创建时间降序),以订单编号进行分组,返回订单列表信息使用Collectors.groupingBy最终返回给前端的数据和分组前有序的订单列表顺序不一致,产生了乱序输出。输出JavaCollectors.groupingBy() 方法默认是使用 HashMap 实现的,而 HashMap 本身并不保证元素顺序。因此,如果需要保证输出顺序,可以使用 Collectors.groupingBy() 的重载方法,并指定一个有序的 Map 实现,例如。 map集合它本身是不能直接转换成Stream流,我们可以选择把map集合,转换成一个单列集合,然后再调用 集合.stream() 方法。实现了Map.Entry接口的对象,实际上每个。Entry对象就是把map集合里面的键和值。返回值是一个set集合,集合里面的每一个元素都是。 来看个小例子: 把菜单的菜按照类型进行分类,有菜的放一组,有肉的放一组,其他的都放另一组。 Map<Dish.Type, List<Dish>> collect = menu.stream().collect(groupingBy(Dish::getType)); 用 Collectors.groupingBy 工厂方法返回的收集器就可以轻松地完成这项任务。 这里,给 groupingBy 方法传递了一个 Function (以方法引用的形式 该存储库包含我在 JDK8/Lambdas/Streams/Collectors 演讲使用的示例文件。 数据文件 mcdonalds.csv、movies-mpaa.txt、ospd.txt 和 words.shakespeare.txt 可以从这里的 Robert Sedgwick 页面免费下载: ://introcs.cs.princeton.edu/java/data/。 顺便说一下,这个页面上还有其他非常有趣的数据集。 你可以在这里找到 3 个例子: 拼字游戏的例子,或者“莎士比亚的拼字游戏会有多好?” 麦克唐纳的例子,或者“休斯顿,我们遇到了问题” 电影数据库示例。 所有文件均在 GPL 许可下提供。 所有数据集文件均受其作者的版权保护,仅为方便起见提供。 更多关于“莎士比亚拼字游戏会有多好”。 我意识到最好的单词实际上无法在拼字游戏播放:没有足够的字母来放置 public class ListToMapTest { public static void main(String[] args) throws ParseException { List<User> users = Arrays.asList( new User("Jack",9), new Use 基于Java8介绍Java stream Collectors.groupingBy 功能 使用 方法,对java Collectors.groupingBy()的可用方法进行一一举例介绍,如stream分组 stream分组计数 stream分组求和 stream分组聚合等,基于stream collect() 和 收集器 Collectors Stream之Collectors.groupingBy(分组)的使用 参考自:https://blog.csdn.net/u014231523/article/details/102535902 Collectors.groupingBy配合Stream流使用,可以对集合一个或多个属性进行分组,分组后还可以做聚合运算。 首先把数据放入集合: Product prod1 = new Product(1L, 1, new BigDecimal("15.5"), "面包", "零食"); Produ // 筛选短信黑名单数据 List smsBlackListSet = allBlacklist.stream().filter(sms -> (sms.getCorpcode().equals(corpCode) && sms.getBltype().equals(MessageTypeEnum.SMS.getKey()) && sms.getSvrtype().equals(bus))).collect(Collectors.toList()); // 解释:本次对allBlacklist集合过滤条件三个:sms.getCorpcode() 之前,针对链式编程的几个方法做了大致的说明。详情可以参考:但实际业务,总会存在很多复杂的思维,需要使用到,此时玩的不熟练总感觉无从下手。以几个案例的形式,展示一些使用流来实现的操作,做一个笔记的记录。因为要考虑使用集合,需要使用到自定义类对象,所以先从定义对象开始。 定义测试数据 有了数据接收对象,现在开始定义数据集合信息,有如下几组数据信息: 此时的集合数据格式如下所示: 如果再数据库,此时的数据格式类似下面这种形式:在一般开发,我们通常期望返回数据样式如下: 此时,通常会采取方式,进行数据的映 Collectors.groupingBy()是Java8的新特性,在日常开发也是比较常用的。根据某些条件进行分组,分组统计,将List转换为map等等。在Java8的源码里面,Collectors.groupingBy()也有几个重载的方法,可以去探究探究。 @Data public class CustTag { private Long id; private Integer num; private String name; priva..