Stream将List转为Map,Set汇总拼接key以及分组groupingBy用法

java Stream操作 转换 这几个函数在日常开发中,也是可以灵活应用的,比如我们DAO操作完数据库,是会有个result的整型结果返回。joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。方法可以帮我们做元素转换,比如一个元素所有字母转化为大写,又或者把获取一个元素对象的某个属性,是一个功能转换型的接口,可以把将一种类型的数据转化为另外一种类型的数据。从数组集合中,过滤掉不符合条件的元素,留下符合条件的元素。是一个消费性接口,通过传入参数,并且无返回的操作。工作中,排序的需求比较多,使用。 阅读详情
AI摘要

本文详细介绍了如何使用Java 8 Stream API进行List到Map的转换,按性别和多层级分组,以及各类统计如订单数、产品数量的求和,筛选购买量最大订单,以及组合分类信息。展示了如何利用`groupingBy`和`Collectors`进行高效的数据处理。

stream求和

直接求和

Integer qty = orderCountVos.stream().mapToInt(e->e.getQty()).sum();

累加器BigDecimal类型求和

 BigDecimal result2 = userList.stream()
                // 将user对象的mongey取出来map为Bigdecimal
                .map(User::getMoney)
                // 使用reduce聚合函数,实现累加器
                .reduce(BigDecimal.ZERO,BigDecimal::add);

Stream将List转换为Map

Stream将List转为Map,Set汇总拼接key以及分组groupingBy用法

转Map

1、指定key-value,value是对象中的某个属性值。

Map<Integer,String> userMap1 = userList.stream().collect(Collectors.toMap(User::getId,User::getName));

2、指定key-value,value是对象本身,User->User 是一个返回本身的lambda表达式

Map<Integer,User> userMap2 = userList.stream().collect(Collectors.toMap(User::getId,User->User));

3、指定key-value,value是对象本身,Function.identity()是简洁写法,也是返回对象本身

Map<Integer,User> userMap3 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

4、指定key-value,value是对象本身,Function.identity()是简洁写法,也是返回对象本身,key 冲突的解决办法,这里选择第二个key覆盖第一个key。

Map<Integer,User> userMap4 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(),(key1,key2)->key2));

拼接key->Map

Map<String, Parts> partsMap = synList.stream().collect(Collectors.toMap(k -> k.getOe()+k.getOeId()+k.getPartGroupId()+k.getStdPartId()+k.getBrandCode(), part -> part));

转set

提取部门ID集合(Set)

Set deptIds = users.stream().map(User::getDeptId).collect(Collectors.toSet());

List拼接字符串

String ids = UserList.map(e->e.getId()).collect(Collectors.joining(“‘,’”));

提取部门ID集合(List)并去重
List deptIds = users.stream().map(User::getDeptId).distinct().collect(Collectors.toList());

set转list

使用构造函数:

Set<Integer> set = new HashSet<>();
// 添加元素到set
List<Integer> list1 = new ArrayList<>(set);

使用addAll()方法

Set<Integer> set = new HashSet<>();
// 添加元素到set
List<Integer> list2 = new ArrayList<>();
list2.addAll(set);

stream的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);

按性别单级分组

//将列表数据按category进行分组
Map<String, List<Product>> categoryMap = prodList.parallelStream()
        .collect(Collectors.groupingBy(Product::getCategory));
 //使用LinkedHashMap,可以保证分组后顺序不变
 Map<String, List<Product>> categoryMap = prodList.parallelStream()
        .collect(Collectors.groupingBy(Product::getCategory, LinkedHashMap::new, Collectors.toList()));

//拿到分组后的map遍历
for (Map.Entry<String, List<Product>> entry : categoryMap .entrySet()) {
	String category= entry.getKey();
	List<Product> ProductList = entry.getValue();
 }

多层级分组

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

 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
			}
		]
	},
	"零食": {
		"3": [
			{
				"category": "零食",
				"id": 1,
				"name": "面包",
				"num": 1,
				"price": 15.5
			},
			{
				"category": "零食",
				"id": 2,
				"name": "饼干",
				"num": 2,
				"price": 20
			}
		],
		"other": [
			{
				"category": "零食",
				"id": 3,
				"name": "月饼",
				"num": 3,
				"price": 30
			}
		]
	}
}

对List<map>分组

idname
1zhangsan
1zhangsan11
2zhangsan2
2zhangsan222
public static void main(String[] args) {
        List<Map<String,Object>> list=new ArrayList<>();
        Map<String,Object> map=new HashMap<>();
        map.put("id",1);
        map.put("name","zhangsan");
        list.add(map);
        Map<String,Object> map2=new HashMap<>();
        map2.put("id",2);
        map2.put("name","wanger");
        list.add(map2);
        Map<String,Object> map3=new HashMap<>();
        map3.put("id",4);
        map3.put("name","zhangsan");
        list.add(map3);
        Map<String,Object> map4=new HashMap<>();
        map4.put("id",4);
        map4.put("name","lisi");
        list.add(map4);
        Map<Integer, List<Map<String, Object>>> id = list.stream().collect(Collectors.groupingBy(item -> {
            return (int)item.get("id");
        }));
 
        id.forEach((k,v)->{
            System.err.println("===========");
            System.err.println("k的值:"+k);
            System.err.println("v的值:");
            v.forEach(System.err::println);
        });
    }


分组结果:
[
1:[
{id:1,name:zhagnhan},{id:1,name:zhagnhan111}
],
2:[
{id:2,name:zhagnhan2},{id:2,name:zhagnhan222}
]
]



按子分组

求和:按分类统计订单数(一个订单算一个)
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
	}
}

分类组合:按类型分组获取产品名称合并的Set集合

联合其他收集器

Map<String, Set> prodMap =
prodList.stream().collect(Collectors.groupingBy(Product::getCategory,
Collectors.mapping(Product::getName, Collectors.toSet())));
 
 分组结果:
{
	"啤酒": [
		"青岛啤酒",
		"百威啤酒"
	],
	"零食": [
		"面包",
		"饼干",
		"月饼"
	]
}

参考文档

java8新特性之groupingBy的用法
https://blog.youkuaiyun.com/CNCDXX_88/article/details/134912054

Stream Collectors.groupingBy的四种用法 解决分组统计(计数、求和、平均数等)、范围统计、分组合并、分组结果自定义映射等问题 基于Java8介绍Java stream Collectors.groupingBy 功能 使用 方法,对java Collectors.groupingBy()的可用方法进行一一举例介绍,如stream分组 stream分组计数 stream分组求和 stream分组聚合等,基于stream collect() 和 收集器 Collectors 阅读详情

相关推荐

Stream流将List转换为map源码分析

Stream流将list转换为Map

weixin_47439116的博客 3031

(stream流)List转Map

(stream流)List转Map的方法如下 第一种(会出现键重复异常): //以id为主键转为map Map<Long, User> map = list.stream().collect(Collectors.toMap(User::getId,Function.identity())); 第二种(针对第一种方法会出现情况): //给出key重复时,使用那个key作为主键,一下代码中的(key1, key2) -> key2)代表key1和key2键重复时返回key2做主键

lizaiismy的博客 7万+

Java Stream groupingBy分组乱序根因分析与有序Map选型指南

在Java集合处理中,Stream API的groupingBy是常用的分组收集器,但很多开发者发现分组后的Map遍历顺序并不符合预期。这背后的核心原理在于groupingBy默认使用HashMap作为结果容器,而HashMap依据哈希散列存储元素,并不保证插入顺序,在数据量较大或发生扩容时顺序更会变得难以捉摸。要解决分组乱序问题,关键在于理解Map容器的顺序语义,并根据业务需要选择合适的Map实现:LinkedHashMap可保持元素的遭遇顺序,TreeMap支持基于比较器的自然或自定义排序。此外,并行流

weixin_34416649的博客 363

List使用stream流转成map的几种方式

List 转成Map List 转成Map List 转成Map List 转成Map List 转成Map List 转成Map

mianxiao15908的博客 4万+

Java Stream groupingBy多字段分组实战:从原理到复杂业务场景

在数据处理领域,分组统计是数据聚合与业务分析的核心基础操作。其原理在于根据特定维度将数据集划分为多个子集,以便进行后续的汇总计算。这项技术的核心价值在于将复杂的过程式逻辑转化为声明式的清晰表达,极大地提升了代码的可读性、可维护性及开发效率。在实际的工程实践中,多维度数据分析是常见需求,例如按部门与职级统计员工分布,或按城市与商品类别分析销售业绩。Java 8引入的Stream API及其`Collectors.groupingBy`方法为此提供了强大支持,通过构建复合键,可以优雅地实现多字段分组。本文将深入

weixin_30632883的博客 343

Java Stream groupingBy()方法详解与实战应用

在数据处理领域,集合分组是常见的操作需求,Java 8引入的Stream API通过Collectors.groupingBy()方法提供了优雅的解决方案。该方法基于函数式编程思想,通过分类函数将元素分组到不同集合中,支持多级分组和多种聚合操作。从技术实现看,groupingBy()底层采用Map结构存储分组结果,支持自定义Map实现和下游收集器处理。在电商订单分析、员工数据统计等场景中,它能显著简化代码并提升可读性。特别是处理大数据集时,结合parallelStream可以实现并行分组计算。相比传统循环方

weixin_30333885的博客 366

List使用stream流转成map的几种方式详解

参考:https://www.jb51.net/article/281570.htm#_label8。

塞北的荒烟的博客 1万+

Java Stream API中Duplicate key异常:原理、排查与解决方案全解析

在Java集合操作与数据处理中,Map作为键值对存储的核心数据结构,其键的唯一性要求是保证数据一致性的基础。当使用Stream API的Collectors.toMap方法进行数据转换时,若遇到重复键,系统会抛出IllegalStateException: Duplicate key异常,这源于Map接口不允许重复键的设计原理。理解这一机制对于处理数据同步、缓存构建及配置加载等场景至关重要。通过分析异常触发的高频场景,如数据库查询结果转换、枚举常量映射及外部数据集成,开发者可以掌握从日志解读、主动排查到预防

weixin_30652897的博客 720

Java stream操作toMap总结

1、map 对象本身,重复的key,放入List。 Map<String, List<Working>> map = workings.stream().collect(Collectors.toMap(Working::getInvoicePage, e -> { ArrayList<Working> list = new Arr

weixin_43928349的博客 1万+

如何打开本地网络的防火墙端口(Windows版)解决ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。问题

ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。 最开始在遇到这个报错的时候十分不解,后来经过思考,有可能是服务器端口占用,或者并没有放行。因此搜查问题的关键是要先去排查问题。 在搜索栏输入控制面板 选择防火墙 选择开关 保证这些选项是开着的 选择高级设置 新建规则 创建协议端口 选择端口 允许连接 点击下一步 创建规则后点击下一步(后命名) 选择任意端口ALL即可 问题排查完毕!socket创建网络通信时,有读者

weixin_46900108的博客 9万+

UE5 Mass交通规则设计指南:从Stop Sign到智能红绿灯的进阶配置

本文详细解析了UE5 Mass框架下的交通规则设计,从基础Stop Sign到智能红绿灯的进阶配置。通过UMassTrafficIntersectionSpawnDataGenerator等核心组件,实现动态响应、自然流畅的交通行为系统,提升虚拟城市的真实感与游戏性。

weixin_30500105的博客 501

Java 8 Stream API 分组聚合实战:从 groupingBy 到复杂数据分析

在数据处理领域,集合的聚合操作是核心需求之一,它涉及将数据元素按照特定规则分组并计算汇总结果。其原理基于函数式编程的声明式范式,通过定义“做什么”而非“怎么做”来提升代码的简洁性与表达力。这种技术价值在于显著减少了传统命令式循环代码的冗余和潜在错误,使逻辑更清晰、更易于维护。在实际应用场景中,无论是电商订单分析、用户行为统计还是财务数据汇总,高效的分组、求和、计数及多维度聚合都是刚需。本文聚焦于 Java 8 引入的 Stream API,特别是其强大的 `Collectors.groupingBy` 方法

weixin_34377919的博客 298

智能座舱语音测试避坑指南:从唤醒率到方言识别,这些场景你测全了吗?

本文深入解析智能座舱语音测试的关键场景与避坑指南,涵盖唤醒率测试、方言识别、多音区交互等复杂场景。通过实战案例与自动化测试方案,帮助开发者全面提升语音系统的可靠性与用户体验,特别关注环境噪声干扰与方言覆盖策略。

weixin_42613501的博客 496

【Stream】Stream将List转Map,Set等互相转换

【代码】【Stream】讲常见数据结构转为map<String,Long>

qq_74776071的博客 94

定制PYNQ的overlay

一、用HLS生成一个定制IP(加速器)(1)首先打开vivado hls,本人的版本是2017.2,点击创建一个新工程。(2)设置工程名和路径,顶层函数设置为add,创建一个新的C++程序,名字叫做adder.cpp,不用在testbench中添加文件。选择板子的时候搜索xc7z020clg400-1,这是PYNQ的板子号,选择完成。             (3)在左侧的菜单栏里选择Sourc...

bramblewalls的博客 1万+

香橙派OPi 6系列选型指南:RK3588与RK3588S开发板深度对比

开发板选型是嵌入式系统设计的关键环节,尤其在边缘计算和AI推理等场景中,芯片的差异直接影响硬件架构。瑞芯微RK3588及其精简版RK3588S是当前高端开发板的核心方案,两者在PCIe通道、显示输出和SATA支持上存在显著区别。理解这些原理,有助于工程师根据项目需求快速匹配产品。香橙派OPi 6系列基于这两款芯片,衍生出OPi 6、OPi 6 Pro与OPi 6 Max三种形态:紧凑型适合嵌入式门禁与AI盒子,Pro版凭借双屏异显和PCIe 3.0满足收银机与视频分析,Max的双2.5G网口和大内存则面向轻

weixin_29185167的博客 222

将List转为Map,属性1 对应 属性2 List

将List转为Map,Map<属性1,List<属性2>> 这种转换帮助我们更加方便的实现集合的整理,我也是在日常工作中遇到的,如果对Stream使用感兴趣的话可以可以关注一下,一起学习; 主要实现就是按照一个类的属性为key,然后把另一个属性作为Value值并且封装为List public class TestDemo { private static final Pattern DELIMITER = Pattern.compile(":"); public st

NANAOO的博客 1039

Ubuntu下Vim创建属于自己的头部注释和代码模板

痛点 每次打开vim想写个C或者C++的程序都要把固定的模板敲一遍,是不是感觉非常的繁琐,能不能把Vim弄得像IDE那样新建一个文件直接生成对应的头部注释和代码模板,减少这些重复工作呢?下面我尽量详细的介绍实现的方法: 先看看新建文件后的效果 C语言格式效果 C++语言效果 方法: 使用命令 vi /etc/vim/vimrc 打开vimrc这个文件,然后复制以下代码至文件末尾的空白处即可! 修改vimrc文件里面的内容必须要用root管理员身份才能进行修改,修改时先切换至root身份即可。 "新建.

weixin_42137584的博客 1559

Java Stream分组后排序:groupingBy顺序控制与并行流避坑

在 Java 集合处理与数据聚合中,Stream API 的 Collectors.groupingBy 常用于按字段分组,但分组后的顺序并不等于业务顺序。其原理在于外层 Map 与内层 List 的顺序语义不同:HashMap 迭代顺序不稳定,ArrayList 依赖遭遇顺序;并行流与 groupingByConcurrent 若搭配非并发下游,还可能破坏组内顺序。正确控制顺序需区分组内元素、组键和组间排序,结合 LinkedHashMap、TreeMap、collectingAndThen、list.s

weixin_34159110的博客 339

52、基于格的具有解密密钥暴露抗性的可撤销(分层)身份基加密方案

本文提出了首个基于格的具有解密密钥暴露抗性(DKER)的可撤销分层身份基加密(RHIBE)方案。通过引入分层密文、分层解密密钥和级别转换密钥等创新工具,克服了格结构与传统密钥重新随机化属性不匹配的难题。该方案不仅支持可扩展的密钥撤销机制,还具备密钥委托功能,为后量子密码学领域的发展提供了新的思路和方法。

efc12345678的博客 123

4-20mA电流信号转电压

该电路实现4-20mA电流信号转电压(0.44-2.2V)调理功能,采用两级运放设计:第一级LMH6642MFX进行11倍放大,第二级配置为缓冲器加二阶低通滤波。电路包含10Ω采样电阻、多级RC滤波和ESD防护,具有抗干扰强、功耗低(4mW)等特点,适配3.3V系统ADC采集。通过使能控制MOS管可实现节能模式,适用于工业自动化、环境监测等场景。设计合理平衡了信号精度与功耗,输出电压范围留有充足余量避免饱和。

qq_37999850的博客 300

Java 8 Stream处理Map:从entrySet到分组聚合的实战指南

在Java集合框架中,Map与Collection的平行设计使其无法直接使用stream(),但通过keySet、values、entrySet三个视图可接入Stream API。其核心原理在于将键值对映射转化为元素流,利用惰性求值与链式操作实现过滤、映射、分组和聚合。这种技术方案显著提升了代码简洁性与数据处理效率,尤其适用于订单统计、用户分组、数据转换等场景。掌握entrySet().stream()的入口写法、Collectors.toMap的冲突处理以及groupingBy的多级分组,能有效避免空指针

weixin_34111790的博客 334

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java Stream集合转换详解:List转Map/Set及互转避坑指南

Java集合是数据容器,Stream则是数据处理管道。理解集合与Stream的分工,才能掌握转换的本质。通过Collector完成可变归约,可以将List转为Map、Set,并实现Map、Set、List间的互转。这种标准化转换逻辑,既提升了代码可读性,也减少了重复key、null value等边界条件导致的错误。日常业务中,无论是按ID构建索引、去重保序,还是分组统计,都离不开List转Map和List转Set这类操作。围绕Stream集合转换的常用写法、底层原理和典型坑点,是快速定位并解决实际开发问题的

weixin_33563728的博客 235

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Java8 中 List 转 Map使用技巧

Java8 中 List 转 Map使用技巧 学习目标: Collectors.toMap相关方法的使用 Collectors.groupingBy相关方法的使用 学习内容: Collectors.toMap //测试1 POJO @Data @NoArgsConstructor @AllArgsConstructor class TestBO { String version; String groupCode; } List<TestBO> list = new Arra

qq_43223477的博客 622

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Java 集合框架(List, Set, Map)练习题

找出两个用户标签列表(List)的共同标签(交集)和独有标签(差集),使用 retainAll() / removeAll() 或 Stream 的 filter + contains,注意大数据量下的性能优化(转为 HashSet 查找)。从 Map 中获取用户配置,若 Key 不存在则返回默认配置对象,使用 Map.getOrDefault() 或 computeIfAbsent() 避免空指针异常(NPE)。‌练习4 — List 转 Map 分组与映射‌。‌练习3 — 集合求交集与差集‌。

weixin_42017951的博客 324

Java 8 List转Map,分组,过滤

先创建一个实体 private Integer id; /** * 登录账号 */ private String loginName; /** * 登录密码 */ private String password; /** * 当前密码 */ private String currentPassword; public TheaterDTO(Integer id, String l

逗比爱好者 276
上一篇: 总结 AT、TCC、Saga、XA 模式分析
下一篇: 自行走机器人系统常用的技术栈
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值