Java8:list转Map

article/2025/8/26 11:24:06

小故事

最近项目中,因为业务需要,我使用了for循环进行List转Map,项目经理看到了,深深的”鄙视“了我,说你怎么写这么古老的写法,一点不优雅。于是我就想到了Java8的新特性,使用stream流进行操作,让代码一下子优雅起来了。

当我们处理一些数据时,将一个列表转换为映射是一个常见的需求。在Java 8中,我们可以使用stream和Lambda表达式、来轻松地将列表转换为映射。在这篇博客文章中,我们将学习如何使用Java 8将List转换为Map。

让我们先来看一个简单的例子,假设我们有一个ApplicationVO类,该类具有id和name属性

古老的for循环

// 需要操作的对象@Data
public class ApplicationVO {// 项目id(唯一)private String appId;// 项目名private String name;// 业务字段 ...public ApplicationVO() {}public ApplicationVO(String appId, String name) {this.appId = appId;this.name = name;}
}// service层代码
// 先看看我的”上古时代“的写法
public static void main(String[] args) {// List<ApplicationVO> applicationVOList = xxDao.queryXXXList(xxx) ; 业务处理List<ApplicationVO> applicationVOList = new ArrayList<>(); // 需要处理的集合// 我先造一些数据List<ApplicationVO> appVOList = Arrays.asList(new ApplicationVO("001", "name1"),new ApplicationVO("002", "name2"),new ApplicationVO("003", "name3"));Map<String, String> map = new HashMap<>();for (ApplicationVO vo : appVOList) {map.put(vo.getAppId(), vo.getName());}System.out.println(map);// ...// 业务处理逻辑}

这里是成功的拿到了Map集合。
在这里插入图片描述
在Java 8中,我们可以使用stream和Lambda表达式来实现这个需求。

Java8:List转Map

使用Collectors.toMap()进行List转Map,stream流操作之前要先给对象进行非空判断,因为Java8Stream对非空判断非常的不友好!

Collectors.toMap() 核心代码

appVOList.stream().collect(Collectors.toMap(ApplicationVO::getAppId, Function.identity(), (key1, key2) -> key2));

下面我给大家说说为什么要这么写!先从源码去理解,这样就能知道为什么要这么干!然后我再举例给大家加深印象。
先看看toMap的源码:
很明显,第一个参数是key值,第二个参数是value值,第三个参数是合并函数,它继承了另一个函数式接口
-> 这种箭头写法叫lambda表达式,不清楚的可以百度恶补一下。

 public static <T, K, U>Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,// key值Function<? super T, ? extends U> valueMapper,// value值BinaryOperator<U> mergeFunction) {return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);}// BinaryOperator源码 
public interface BinaryOperator<T> extends BiFunction<T,T,T> {public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {Objects.requireNonNull(comparator);return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; // 返回两个元素中较小的一个}public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {Objects.requireNonNull(comparator);return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;// 返回两个元素中较大的一个}
}

第一种:key为属性,value为对象

示范

  public static void main(String[] args) {// List<ApplicationVO> applicationVOList = xxDao.queryXXXList(xxx) ; 业务处理List<ApplicationVO> applicationVOList = new ArrayList<>(); // 需要处理的集合// 我先造一些数据List<ApplicationVO> appVOList = Arrays.asList(new ApplicationVO("001", "name1"),new ApplicationVO("002", "name2"),new ApplicationVO("003", "name3"));// 对集合做非空判断,java8对空对象不友好Map<String, ApplicationVO> voMap= appVOList.stream().collect(Collectors.toMap(ApplicationVO::getAppId, Function.identity(), (key1, key2) -> key2));System.out.println(voMap);// ...// 业务处理逻辑}

在这里插入图片描述

上面这种写法,原本四行代码,现在只需要一行代码就能表达出来。(如果大家公司有代码量考核,我不建议大家跟我一样优雅起来 /手动滑稽)

Function.identity()

在转Map的时候的一种固定写法,当然也可以自己改造,源码是说输入什么输出什么,如果为了可读性,你也可以将这段代码写成 str ->str之类的写法,至于怎么写,也没有说哪种写法更好,但是我本人更倾向于function的这种写法。

static <T> Function<T, T> identity() {return t -> t;}

(key1, key2) -> key2

可能大家已经看到我这个写法了,是不是看着就很高级,很优雅?这个其实是我自己在开发中遇到的一个坑,由于没有写这个,在key重复的时候,抛出了异常,很是恼火,于是当然也想第一次使用一样,不懂,于是点进源码瞅了瞅,然后查阅资料,于是乎就出现了上面我这种写法:(key1, key2) -> key2,它的意思是如果两个key重复了,让后面的key覆盖前面的key,完美解决bug,嘻嘻。
给大家演示一下key重复会抛出什么异常把:

public static void main(String[] args) {// List<ApplicationVO> applicationVOList = xxDao.queryXXXList(xxx) ; 业务处理List<ApplicationVO> applicationVOList = new ArrayList<>(); // 需要处理的集合// 我先造一些数据List<ApplicationVO> appVOList = Arrays.asList(new ApplicationVO("001", "name1"),new ApplicationVO("002", "name2"),new ApplicationVO("003", "name3"),new ApplicationVO("003", "name3") // 这里出现了两个人一个姓名,那不得打起来0.0);// 对集合做非空判断,java8对空对象不友好Map<String, String> voMap = appVOList.stream().collect(Collectors.toMap(ApplicationVO::getAppId, vo -> vo.getName() + "你好帅"));System.out.println(voMap);// ...// 业务处理逻辑}

在这里插入图片描述

第二种:key为属性,value也为属性

示范

 public static void main(String[] args) {// List<ApplicationVO> applicationVOList = xxDao.queryXXXList(xxx) ; 业务处理List<ApplicationVO> applicationVOList = new ArrayList<>(); // 需要处理的集合// 我先造一些数据List<ApplicationVO> appVOList = Arrays.asList(new ApplicationVO("001", "name1"),new ApplicationVO("002", "name2"),new ApplicationVO("003", "name3"));// 对集合做非空判断,java8对空对象不友好Map<String, String> voMap= appVOList.stream().collect(Collectors.toMap(ApplicationVO::getAppId, ApplicationVO::getName, (key1, key2) -> key2));System.out.println(voMap);// ...// 业务处理逻辑}

在这里插入图片描述
是不是很优雅,一行代码解决,key为appid,value是name字段,具体如何使用,根据业务需要来进行处理,如果只需要某个字段,建议这一种,毕竟像上面的第一种,直接返回整个对象的,更加的消耗内存。

第三种:对value值进行操作的

示范

public static void main(String[] args) {// List<ApplicationVO> applicationVOList = xxDao.queryXXXList(xxx) ; 业务处理List<ApplicationVO> applicationVOList = new ArrayList<>(); // 需要处理的集合// 我先造一些数据List<ApplicationVO> appVOList = Arrays.asList(new ApplicationVO("001", "name1"),new ApplicationVO("002", "name2"),new ApplicationVO("003", "name3"));// 对集合做非空判断,java8对空对象不友好Map<String, String> voMap= appVOList.stream().collect(Collectors.toMap(ApplicationVO::getAppId, vo -> vo.getName() + "你好帅", (key1, key2) -> key2));System.out.println(voMap);// ...// 业务处理逻辑}

在这里插入图片描述

补充第四种:多个属性拼接成key,value为属性(或者对象)

 // 实例
public static void main(String[] args) {List<TopicVO> topicList = Arrays.asList(new TopicVO(1, 10, "主题1"),new TopicVO(2, 20, "主题2"),new TopicVO(3, 30, "主题3"));// 属性id和属性name组装成key,value值为age字段Map<String, Integer> topicMap= topicList.stream().collect(Collectors.toMap(vo -> vo.getId() + vo.getName(), TopicVO::getAge));System.out.println(topicMap);}

在这里插入图片描述

写在最后

本文从toMap底层介绍了一下Java8如何更加优雅的写出List转Map,避免大家跟我一样,在开发中被”叼“,希望大家学以致用,跟我一样,写优雅的代码。

Tips

上面基本上是我遇到的坑,希望遇到一次少一次,给大家留个问题,也是我思考过的:使用Java8一定优雅吗?效率一定高吗?什么时候for循环效率更高?欢迎大家给我留言,写这篇文章,可花了我不少时间和心思哦,喜欢的点个赞把。


http://chatgpt.dhexx.cn/article/qlK2xSOx.shtml

相关文章

Java8 Stream(11)List转Map

一、前言 对于聚合统计可以参考下面博客。 Java8 Stream&#xff08;12&#xff09;Collectors 分组统计 详解 开发中&#xff0c;List转Map是非常常见的操作&#xff0c;例如&#xff1a; List<T> 转 Map<String, T>List<T> 转 Map<String, List<T&…

APP移动测试用例总结,总有你要用到的

目录 前言 一、首先是测试资源确认及准备 二、测试用例的设计与评审 三、UI测试 四、功能测试 五、中断测试 六、兼容性及适配测试 七、性能测试 八、稳定性测试 九、测试分析及测试报告输出 十、移动端测试用例的实践经验 总结 重点&#xff1a;配套学习资料和…

设计水杯,门锁的测试用例

测试用例公式&#xff1a; 功能测试 界面测试 性能测试 兼容性测试 易用性测试 安全测试 一般用脑图或者Excel来编写测试用例 百度脑图 - 便捷的思维工具 水杯的测试用例&#xff1a; 门锁的测试用例&#xff1a; 测试用例越多越好吗&…

APP 测试用例(大部分 APP 通用)

APP 测试用例 根据 场景设计法 来设计测试用例 安装与卸载权限设置软件更新登录与注册网络环境运行日历控件异常测试兼容性测试

在线音乐播放器测试用例

登录功能测试用例 当用户输入正确的用户名和密码时,方可登录成功,否则,会给出相应得提示。 上传音乐测试用例 用户选择上传的音乐后缀是.mp3时,才能上传成功。 查询音乐测试用例 查询音乐支持指定名称查询和模糊匹配查询。 安全测试 安全测试作为系统测试的主要部分&#xff0c…

APP移动测试用例总结

目录 前言 一、首先是测试资源确认及准备 二、测试用例的设计与评审 三、UI测试 四、功能测试 五、中断测试 六、兼容性及适配测试 七、性能测试 八、稳定性测试 九、测试分析及测试报告输出 十、移动端测试用例的实践经验 结语 前言 在我们的测试工作中&#xff0c;对于某…

手机app测试用例怎么写?手机app测试点有哪些?没有水分,错过绝对后悔

目录 一、前言 二、安装卸载测试点 安装测试 卸载测试 三、登录注册测试点 登录测试点 注册测试点 四、更新推送测试点 数据更新 消息推送 五、还有易用性&#xff0c;兼容性&#xff0c;安全性太多了&#xff01; 一、前言 在当今竞争激烈的市场上一个APP的成功离不…

淘宝APP购物车测试用例

淘宝APP购物车测试用例 淘宝购物车界面界面测试&#xff1a; 1、打开页面后&#xff0c;页面显示是否完整&#xff0c;页面布局是否合理。&#xff08;1&#xff09;标题、宝贝数显示、降价提示、管理。&#xff08;2&#xff09;字体大小、字体格式。 2、不同店家的商品在不…

手机app测试用例怎么写?手机app测试点有哪些?

随着科技的发展&#xff0c;购物、旅游、支付等日常衣食住行活动都离不开手机&#xff0c;由此衍生了很多APP。比如每天使用频率非常高的微信、支付宝、微博、抖音、王者荣耀等等。APP测试主要进行功能测试、性能测试、自动化测试、安全性测试、兼容性测试、专项测试。 APP测试…

app测试用例

app主要测试类型&#xff1a;安全性、易用性、性能、安装卸载、注册登录、兼容性、更新推送。 1、安全性&#xff1a;权限测试、安装卸载安全性、密码显示存储及长度要求、数据安全性、敏感数据的处理、备份与恢复要求、安全提示要求、数据删除要求、个人信息的使用要求、应用…

手机app测试用例怎么写?手机app测试点有哪些?只有干货没有水分,错过绝对后悔!

目录 一、前言 二、安装卸载测试点 安装测试 卸载测试 三、登录注册测试点 登录测试点 注册测试点 四、更新推送测试点 数据更新 消息推送 五、还有易用性&#xff0c;兼容性&#xff0c;安全性太多了&#xff01; 一、前言 在当今竞争激烈的市场上一个APP的成功离不…

牛顿法与拟牛顿法学习笔记(三)DFP 算法

机器学习算法中经常碰到非线性优化问题&#xff0c;如 Sparse Filtering 算法&#xff0c;其主要工作在于求解一个非线性极小化问题。在具体实现中&#xff0c;大多调用的是成熟的软件包做支撑&#xff0c;其中最常用的一个算法是 L-BFGS。为了解这个算法的数学机理&#xff0c…

拟牛顿法 分析与推导

转自 http://www.cnblogs.com/liuwu265/p/4714396.html &#xff0c;侵删 网上查拟牛顿法的推导&#xff0c;找到一个感觉比较容易读懂的&#xff0c;保存下来 针对牛顿法中海塞矩阵的计算问题&#xff0c;拟牛顿法主要是使用一个海塞矩阵的近似矩阵来代替原来的还塞矩阵&…

优化算法——拟牛顿法之BFGS算法

一、BFGS算法简介 BFGS算法是使用较多的一种拟牛顿方法&#xff0c;是由Broyden&#xff0c;Fletcher&#xff0c;Goldfarb&#xff0c;Shanno四个人分别提出的&#xff0c;故称为BFGS校正。 同DFP校正的推导公式一样&#xff0c;DFP校正见博文“ 优化算法——拟牛顿法之DFP算法…

牛顿法的matlab实现

简介&#xff1a;牛顿法是用来求解无约束优化问题的&#xff0c;它的基本思想是用迭代点xk处的一阶导数和二阶导数对目标函数进行二次函数近似&#xff0c;然后把二次模型的极小点作为新的迭代点&#xff0c;不断重复这一过程&#xff0c;直至满足精度的近似极小点。 这里有必…

最优化方法:牛顿迭代法和拟牛顿迭代法

http://blog.csdn.net/pipisorry/article/details/24574293 基础 拐点 若曲线图形在一点由凸转凹&#xff0c;或由凹转凸&#xff0c;则称此点为拐点。直观地说&#xff0c;拐点是使切线穿越曲线的点。 拐点的必要条件&#xff1a;设 f ( x ) {\displaystyle f(x)} 在 ( a , b…

Newton法(牛顿法 Newton Method)

平时经常看到牛顿法怎样怎样&#xff0c;一直不得要领&#xff0c;今天下午查了一下维基百科&#xff0c;写写我的认识&#xff0c;很多地方是直观理解&#xff0c;并没有严谨的证明。在我看来&#xff0c;牛顿法至少有两个应用方向&#xff0c;1、求方程的根&#xff0c;2、最…

牛顿法与拟牛顿法学习笔记(四)BFGS 算法

机器学习算法中经常碰到非线性优化问题&#xff0c;如 Sparse Filtering 算法&#xff0c;其主要工作在于求解一个非线性极小化问题。在具体实现中&#xff0c;大多调用的是成熟的软件包做支撑&#xff0c;其中最常用的一个算法是 L-BFGS。为了解这个算法的数学机理&#xff0c…