Java 集合数据处理技巧:使用 Stream API 实现多种操作

20250217135513828919.png

在 Java 开发中,对集合数据进行处理是非常常见的需求,例如去重、排序、分组、求和等。Java 8 引入的 Stream API 为我们提供了一种简洁、高效的方式来处理集合数据。本文将详细介绍如何使用 Stream API 实现多种集合数据处理操作,并给出相应的代码示例。

1. List 根据某个属性去重

在处理 List​ 数据时,有时需要根据对象的某个属性进行去重。可以使用 TreeSet​ 和 Stream​ 来实现这一功能。以下是示例代码:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;// 定义 SKU 类
class SKU {private String gid;public SKU(String gid) {this.gid = gid;}public String getGid() {return gid;}
}public class ListDistinctByProperty {public static void main(String[] args) {List<SKU> skuList = new ArrayList<>();skuList.add(new SKU("1"));skuList.add(new SKU("2"));skuList.add(new SKU("1"));ArrayList<SKU> skus = skuList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SKU::getGid))), ArrayList::new));skus.forEach(sku -> System.out.println(sku.getGid()));}
}

在上述代码中,首先创建了一个 SKU​ 类,包含 gid​ 属性。然后使用 Stream​ 对 skuList​ 进行处理,通过 Collectors.toCollection​ 将其转换为 TreeSet​,利用 TreeSet​ 的特性根据 gid​ 去重,最后再将 TreeSet​ 转换为 ArrayList​。

2. 指定字段排序

2.1 升序排序

可以使用 Stream​ 的 sorted​ 方法和 Comparator.comparing​ 来实现指定字段的升序排序。以下是示例代码:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;// 定义 Order 类
class Order {private long createTime;public Order(long createTime) {this.createTime = createTime;}public long getCreateTime() {return createTime;}
}public class ListSortAsc {public static void main(String[] args) {List<Order> orderList = new ArrayList<>();orderList.add(new Order(3));orderList.add(new Order(1));orderList.add(new Order(2));List<Order> sortedList = orderList.stream().sorted(Comparator.comparing(Order::getCreateTime)).collect(Collectors.toList());sortedList.forEach(order -> System.out.println(order.getCreateTime()));}
}

2.2 降序排序

如果需要降序排序,只需在 Comparator.comparing​ 后调用 reversed​ 方法。以下是示例代码:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;// 定义 Order 类
class Order {private long createTime;public Order(long createTime) {this.createTime = createTime;}public long getCreateTime() {return createTime;}
}public class ListSortDesc {public static void main(String[] args) {List<Order> orderList = new ArrayList<>();orderList.add(new Order(3));orderList.add(new Order(1));orderList.add(new Order(2));List<Order> sortedList = orderList.stream().sorted(Comparator.comparing(Order::getCreateTime).reversed()).collect(Collectors.toList());sortedList.forEach(order -> System.out.println(order.getCreateTime()));}
}

2.3 null 排前面

如果需要将 null​ 值排在前面,可以使用 Comparator.nullsFirst​ 方法。以下是示例代码:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;// 定义 LuckyBoysVo 类
class LuckyBoysVo {private Date usageTime;public LuckyBoysVo(Date usageTime) {this.usageTime = usageTime;}public Date getUsageTime() {return usageTime;}
}public class ListSortNullFirst {public static void main(String[] args) {List<LuckyBoysVo> luckyBoysList = new ArrayList<>();luckyBoysList.add(new LuckyBoysVo(new Date(2000)));luckyBoysList.add(new LuckyBoysVo(null));luckyBoysList.add(new LuckyBoysVo(new Date(1000)));List<LuckyBoysVo> luckyBoysVoList = luckyBoysList.stream().sorted(Comparator.comparing(LuckyBoysVo::getUsageTime, Comparator.nullsFirst(Date::compareTo))).collect(Collectors.toList());luckyBoysVoList.forEach(vo -> System.out.println(vo.getUsageTime()));}
}

3. 指定字段相同,指定值计算和

可以使用 Collectors.groupingBy​ 方法对数据进行分组,然后使用 reduce​ 方法计算相同字段对应的值的和。以下是示例代码:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;// 定义 ExportAgentVo 类
class ExportAgentVo {private String dealCode;private String agentId;private String goodsId;private String goodName;private int count;private String name;private String address;public ExportAgentVo(String dealCode, String agentId, String goodsId, String goodName, int count, String name, String address) {this.dealCode = dealCode;this.agentId = agentId;this.goodsId = goodsId;this.goodName = goodName;this.count = count;this.name = name;this.address = address;}public String getDealCode() {return dealCode;}public String getAgentId() {return agentId;}public String getGoodsId() {return goodsId;}public String getGoodName() {return goodName;}public int getCount() {return count;}public String getName() {return name;}public String getAddress() {return address;}
}public class ListSumByField {public static void main(String[] args) {List<ExportAgentVo> exportAgentVoList = new ArrayList<>();exportAgentVoList.add(new ExportAgentVo("1", "A", "G1", "Good1", 10, "Name1", "Addr1"));exportAgentVoList.add(new ExportAgentVo("2", "A", "G1", "Good1", 20, "Name1", "Addr1"));List<ExportAgentVo> exportAgentVoListResult = new ArrayList<>();exportAgentVoList.stream().collect(Collectors.groupingBy(o -> (o.getGoodsId() + o.getAgentId()), Collectors.toList())).forEach((id, transfer) -> {transfer.stream().reduce((a, b) ->new ExportAgentVo(a.getDealCode(),a.getAgentId(),a.getGoodsId(),a.getGoodName(),a.getCount() + b.getCount(), a.getName(), a.getAddress())).ifPresent(exportAgentVoListResult::add);});exportAgentVoListResult.forEach(vo -> System.out.println(vo.getCount()));}
}

4. 指定字段相同,计算相同个数

可以使用 Collectors.groupingBy​ 和 Collectors.counting​ 方法来计算指定字段相同的个数。以下是示例代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;// 定义 TkDetailMaskLayerMapping 类
class TkDetailMaskLayerMapping {private String maskId;public TkDetailMaskLayerMapping(String maskId) {this.maskId = maskId;}public String getMaskId() {return maskId;}
}public class ListCountByField {public static void main(String[] args) {List<TkDetailMaskLayerMapping> list = new ArrayList<>();list.add(new TkDetailMaskLayerMapping("M1"));list.add(new TkDetailMaskLayerMapping("M1"));list.add(new TkDetailMaskLayerMapping("M2"));Map<String, Long> map = list.stream().collect(Collectors.groupingBy(TkDetailMaskLayerMapping::getMaskId, Collectors.counting()));map.forEach((key, value) -> System.out.println(key + ": " + value));}
}

5. 指定字段分组

可以使用 Collectors.groupingBy​ 方法对 List​ 进行指定字段分组。以下是示例代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;// 定义 ExportAgentVo 类
class ExportAgentVo {private String agentId;public ExportAgentVo(String agentId) {this.agentId = agentId;}public String getAgentId() {return agentId;}
}public class ListGroupByField {public static void main(String[] args) {List<ExportAgentVo> exportAgentVoListResult = new ArrayList<>();exportAgentVoListResult.add(new ExportAgentVo("A1"));exportAgentVoListResult.add(new ExportAgentVo("A2"));exportAgentVoListResult.add(new ExportAgentVo("A1"));Map<String, List<ExportAgentVo>> exportAgentVoMap = exportAgentVoListResult.stream().collect(Collectors.groupingBy(ExportAgentVo::getAgentId));exportAgentVoMap.forEach((key, value) -> System.out.println(key + ": " + value.size()));}
}

6. 分组并求和

可以使用 Collectors.groupingBy​ 和 Collectors.summingInt​ 方法对数据进行分组并求和。以下是示例代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;// 定义 ExportGoodsProcurementDetailVo 类
class ExportGoodsProcurementDetailVo {private String supplierName;private String agentId;private String goodsId;private int count;public ExportGoodsProcurementDetailVo(String supplierName, String agentId, String goodsId, int count) {this.supplierName = supplierName;this.agentId = agentId;this.goodsId = goodsId;this.count = count;}public String getSupplierName() {return supplierName;}public String getAgentId() {return agentId;}public String getGoodsId() {return goodsId;}public int getCount() {return count;}
}public class ListGroupAndSum {public static void main(String[] args) {List<ExportGoodsProcurementDetailVo> goodsProcurementDetailVos = new ArrayList<>();goodsProcurementDetailVos.add(new ExportGoodsProcurementDetailVo("S1", "A1", "G1", 10));goodsProcurementDetailVos.add(new ExportGoodsProcurementDetailVo("S1", "A1", "G1", 20));ExportGoodsProcurementDetailVo exportGoodsProcurementDetailVo = new ExportGoodsProcurementDetailVo("S1", "A1", "", 0);ExportGoodsProcurementDetailVo exportGoBeerVo = new ExportGoodsProcurementDetailVo("", "A1", "", 0);Map<String, Integer> goodCountMap = goodsProcurementDetailVos.stream().filter(a -> a.getSupplierName().equals(exportGoodsProcurementDetailVo.getSupplierName())&& a.getAgentId().equals(exportGoBeerVo.getAgentId())).collect(Collectors.groupingBy(ExportGoodsProcurementDetailVo::getGoodsId,Collectors.summingInt(ExportGoodsProcurementDetailVo::getCount)));goodCountMap.forEach((key, value) -> System.out.println(key + ": " + value));}
}

7. List 转 Map

可以使用 Collectors.toMap​ 方法将 List​ 转换为 Map​。需要注意的是,如果集合对象有重复的 key​,会报错 Duplicate key​,可以使用 (k1, k2) -> k1​ 来处理重复 key​ 的情况。以下是示例代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;// 定义 CustomerDetailResp 类
class CustomerDetailResp {private String dept;private String members;public CustomerDetailResp(String dept, String members) {this.dept = dept;this.members = members;}public String getDept() {return dept;}public String getMembers() {return members;}
}// 定义 Apple 类
class Apple {private int id;public Apple(int id) {this.id = id;}public int getId() {return id;}
}public class ListToMap {public static void main(String[] args) {List<CustomerDetailResp> result = new ArrayList<>();result.add(new CustomerDetailResp("D1", "M1"));result.add(new CustomerDetailResp("D2", "M2"));Map<String, String> map1 = result.stream().collect(Collectors.toMap(CustomerDetailResp::getDept, CustomerDetailResp::getMembers));Map<String, CustomerDetailResp> map2 = result.stream().collect(Collectors.toMap(CustomerDetailResp::getDept, CustomerDetailResp -> CustomerDetailResp));List<Apple> appleList = new ArrayList<>();appleList.add(new Apple(1));appleList.add(new Apple(1));Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a, (k1, k2) -> k1));}
}

8. List 转 String

可以使用 Google Guava 库的 Joiner​ 类将 List​ 转换为 String​。以下是示例代码:

import com.google.common.base.Joiner;
import java.util.ArrayList;
import java.util.List;public class ListToString {public static void main(String[] args) {List<String> itemNoList = new ArrayList<>();itemNoList.add("1");itemNoList.add("2");itemNoList.add("3");String join = Joiner.on(',').join(itemNoList);System.out.println(join);}
}

9. String 转 List

可以使用 Arrays.stream​ 和 Collectors.toList​ 方法将 String​ 转换为 List​。以下是示例代码:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StringToList {public static void main(String[] args) {String sales = "1,2,3,2";List<String> saleList = Arrays.stream(sales.split(",")).distinct().collect(Collectors.toList());saleList.forEach(System.out::println);}
}

通过以上示例,我们可以看到 Java 8 的 Stream API 为集合数据处理提供了非常强大和便捷的功能。合理使用这些功能可以大大提高代码的可读性和开发效率。本文示例已涵盖日常开发中90%的集合处理场景,建议根据具体业务需求灵活组合使用。对于更复杂的操作,可结合Collectors.joining、mapping等收集器实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21477.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络基础杂谈(局域网、ip、子网掩码、网关、DNS)

目录 1. 简单局域网的构成 2. IP 地址 3. 子网掩码 4. IP地址详解自定义IP 5. IP 地址详解 6. 网关 7. DNS 域名解析 8. ping 1. 简单局域网的构成 交换机是组建局域网最重要的设备&#xff0c;换句话说&#xff0c;没有交换机就没法搭建局域网 交换机不能让局域网连…

基于SpringBoot的高校教学资料管理系统的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

Rust 未来会成为主流的编程语言吗?

Rust是由Mozilla团队主导开发的编程语言&#xff0c;首次亮相是在2010年。自发布以来&#xff0c;Rust凭借其内存安全性、出色的性能和对并发操作的支持&#xff0c;逐渐吸引了众多开发者的关注。据Stack Overflow的2021年调查数据显示&#xff0c;Rust连续多年被开发者评为最喜…

【Java】代理模式

代理模式 代理模式是指给某一个对象提供一个代理&#xff0c;并由代理对象来控制对真实对象的访问 代理模式是一种结构型设计模式 背景 如果不采用代理&#xff0c;对一个类的多个方法进行监控时&#xff0c;重复的代码总是重复出现&#xff0c;不但破坏了原方法&#xff0c;…

STM32 看门狗

目录 背景 独立看门狗&#xff08;IWDG&#xff09; 寄存器访问保护 窗口看门狗&#xff08;WWDG&#xff09; 程序 独立看门狗 设置独立看门狗程序 第一步、使能对独立看门狗寄存器的写操作 第二步、设置预分频和重装载值 第三步、喂狗 第四步、使能独立看门狗 喂狗…

LLM论文笔记 15: Transformers Can Achieve Length Generalization But Not Robustly

Arxiv日期&#xff1a;2024.2.14机构&#xff1a;Google DeepMind / University of Toronto 关键词 长度泛化位置编码数据格式 核心结论 1. 实验结论&#xff1a;十进制加法任务上的长度泛化最佳组合&#xff1a; FIRE位置编码 随机化位置编码 反向数据格式 索引提示&…

超详细!一文搞定PID!嵌入式STM32-PID位置环和速度环

本文目录 一、知识点1. PID是什么&#xff1f;2. 积分限幅--用于限制无限累加的积分项3. 输出值限幅--用于任何pid的输出4. PID工程 二、各类PID1. 位置式PID&#xff08;用于位置环&#xff09;&#xff08;1&#xff09;公式&#xff08;2&#xff09;代码使用代码 2. 增量式…

【Linux探索学习】第二十八弹——信号(下):信号在内核中的处理及信号捕捉详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在前面我们已经学习了有关信号的一些基本的知识点&#xff0c;包括&#xff1a;信号的概念、信号产生和信号处理等&#xff0c;今天我们重…

Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件

一.类的介绍 1.QPdfWriter介绍 Qt中提供了一个直接可以处理PDF的类&#xff0c;这就是QPdfWriter类。 &#xff08;1&#xff09;PDF文件生成 支持创建新的PDF文件或覆盖已有文件&#xff0c;通过构造函数直接绑定文件路径或QFile对象&#xff1b; 默认生成矢量图形PDF&#…

快速上手gdb/cgdb

Linux调试器-gdb使用 1.背景2.调试原理、技巧命令2.1指令2.2 本质2.3 技巧 1.背景 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 要使用gdb调试&#xff0c;必须在源代码生成二进制程序的时候, 加上 -g…

linux网络编程(1.5w字+内部程序理解网络)

目录 核心大图&#xff1a; 网络字节序 网络字节序与主机字节序 地址转换函数 一、inet_ntoa函数 二、inet_aton函数 三、inet_aton和inet_ntoa的测试 in_addr转字符串的函数: socket编程接口 socket 常见API 1.socket 参数1&#xff1a;int af 参数2&#xff1a;…

windows环境下用docker搭建php开发环境dnmp

安装WSL WSL即Linux子系统&#xff0c;比虚拟机占用资源少&#xff0c;安装的前提是系统必须是win10以上。 WSL的安装比较简单&#xff0c;网上有很多教程&#xff0c;例如&#xff1a;WSL简介与安装流程&#xff08;Windows 下的 Linux 子系统&#xff09;_wsl安装-CSDN博客&…

Nginx之rewrite重写功能

目录 一、rewrite概述 1、rewrite功能 2、跳转场景 二、标准配置指令 1、rewrite日志记录指令 2、未初始化变量告警日志记录指令 3、rewrite 指令 3.1 正则表达式 三、rewrite模块使用实例 1.基于域名的跳转 2.基于客户端 IP 访问跳转 3.?基于旧域名跳转到新域名后…

Mybatis(一)

配置文件 必要的用户密码要修改, 还有绿色线的名字要修改成数据库的 配置文件直接cv 创建 复习之前的知识进行分层处理 与前面一一对应, 后面三个发现后面输出是null, 没有一一对应, 后面再解释解决方法 运行发现, 输出正常 idea的测试类 两个注解了解 记得加上这个, 不然无…

一周学会Flask3 Python Web开发-http响应状态码

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在Flask程序中&#xff0c;客户端发出的请求触发相应的视图函数&#xff0c;获取返回值会作为响应的主体&#xff0c;最后生成…

七星棋牌源码高阶技术指南:6端互通、200+子游戏玩法深度剖析与企业级搭建实战(完全开源)

在棋牌游戏行业高速发展的今天&#xff0c;如何构建一个具备高并发、强稳定性与多功能支持的棋牌游戏系统成为众多开发者和运营团队关注的焦点。七星棋牌全开源修复版源码 凭借其 六端互通、200子游戏玩法、多省区本地化支持&#xff0c;以及 乐豆系统、防沉迷、比赛场、AI智能…

C++和OpenGL实现3D游戏编程【总览】

欢迎来到zhooyu的游戏专栏。 主页网址&#xff1a;【zhooyu】 专栏网址&#xff1a;【C和OpenGL实现3D游戏编程】 &#x1f31f;&#x1f31f;&#x1f31f;这里将通过一个OpenGL实现3D游戏编程实例教程&#xff0c;带大家深入学习OpenGL知识。知识无穷而人力有穷&#xff0c;…

pycharm社区版有个window和arm64版本,到底下载哪一个?还有pycharm官网

首先pycharm官网是这一个。我是在2025年2月16日9:57进入的网站。如果网站还没有更新的话&#xff0c;那么就往下滑一下找到 community Edition,这个就是社区版了免费的。PyCharm&#xff1a;适用于数据科学和 Web 开发的 Python IDE 适用于数据科学和 Web 开发的 Python IDE&am…

GPT-Sovits:语音克隆训练-遇坑解决

前言 本来以为3050完全无法执行GPT-Sovits训练的&#xff0c;但经过实践发现其实是可以&#xff0c;并且仅花费了十数分钟便成功训练和推理验证了自己的语音模型。 官方笔记&#xff1a;GPT-SoVITS指南 语雀 项目地址&#xff1a;https://github.com/RVC-Boss/GPT-SoVITS 本人…

8 SpringBootWeb案例(上): 查询【分页功能(分页插件)】、删除、新增、修改

文章目录 前言:SpringBootWeb案例1. 准备工作1.1 需求&环境搭建1.1.1 需求说明1.1.2 环境搭建1.2 开发规范1.2.1 开发规范-REST(不强求非要这种风格,传统风格有时候更方便)1.2.2 开发规范-统一响应结果和异常处理1.2.3 开发流程2. 部门管理2.1 查询部门2.1.1 原型和需求…