Java8 Lambda如何高效构建多层嵌套Map?

2026-05-25 20:531阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1253个文字,预计阅读时间需要6分钟。

Java8 Lambda如何高效构建多层嵌套Map?

目录 + 使用Lambda快速生成map、多层嵌套map + List转换为Map(id, bean) + 一主多子javaBean List转换为Map(id, Map(id, itemBean)) + 常见代码异味——多层嵌套,缺乏封装 1. 多层嵌套 2. 缺乏封装,利用Lambda快速生成

目录
  • 利用Lambda快速生成map、多层嵌套map
    • List 转为 Map<id, bean>
    • 一主多子 javaBean List 转为 Map<id, Map<id, itemBean> >
  • 常见的代码坏味道--多层嵌套,缺乏封装
    • 1. 多层嵌套
    • 2. 缺乏封装

利用Lambda快速生成map、多层嵌套map

List 转为 Map<id, bean>

  • User是List对象的元素,List
  • List对象的变量名为:userList
  • id 将作为 Map 的 Key

Map<String, User> idMap = userList.stream().collect( Collectors.toMap(User::getId, b->b) );

一主多子 javaBean List 转为 Map<id, Map<id, itemBean> >

  • 一主,主Bean: User
  • 多子,子Bean: UserItem
  • 集合:List
  • 转Map:Map<User_id, Map <UserItem_id, UserItem> >

一主多子的主javaBean为List对象的元素,List

此处List对象的变量为:userList

Map<String, Map<String, UserItem>> collect =      userList.stream().collect(         Collectors.toMap(             User::getId, b -> {                 return b.getUserItem().stream().collect(                         Collectors.toMap(UserItem::getId, c -> c)                 );             }         )     );

常见的代码坏味道--多层嵌套,缺乏封装

1. 多层嵌套

多层嵌套的两个原因

1.1if else

最简单的重构手法,提前 return ,也叫 Replace Nested Conditional with Guard Clauses 卫语句。

有一些比较激进的看法认为 else 本身就是一种坏味道。

可以使用 idea 的插件 Checkstyle 检查一下代码的 圈复杂度。当圈复杂度大于某个值的时候,就会报错。

圈复杂度的这部分代码中线性无关路径的数量。

如果一段源码中不包含控制流语句(条件或决策点),那么这段代码的圈复杂度为1,因为这段代码中只会有一条路径;如果一段代码中仅包含一个if语句,且if语句仅有一个条件,那么这段代码的圈复杂度为2;包含两个嵌套的if语句,或是一个if语句有两个条件的代码块的圈复杂度为3。

第二种解决过多判断的方案是多态,这就要求从设计阶段就开始考虑实现方案。

注意多态的本质是想要实现对拓展开发,对修改关闭,所以如果继承的层级较多,逻辑比较复杂,就会导致适得其反的效果。

1.2 for 循环

对集合进行循环操作推荐使用java8的Stream操作(,mapreduce,map代表操作,collect代表reduce),比如。从本质上讲Stream也是循环,但是这种语法糖的形式会对各种操作进行分类,进行合理的优化处理。

循环和函数式编程的区别不仅仅在写法上,更体现在思想上。前者描述实现细节,后者描述做什么。

当然,如果在列表转换中使用过多的 lambda 表达式,会导致看起来很吃力,不好理解。这时候长的lambda本身可以提取成为方法。

2. 缺乏封装

2.1. 过长的消息链或者说火车残骸

第一种缺乏封装的表现是java类处理不当,可能是设计的太粗糙,面向过程实现业务逻辑导致的。这就要求开发的时候进行更多的抽象。

比如,不是所有的java类都直接提供所有的getter setter 方法就行,还要根据业务场景进行合理选择;另外对象内部的细节不需要过多的暴露出去,应该做适当的封装。

2.2 基本类型的偏执

第二种更高级的缺乏封装,是指用基本类型代表所有的业务数据。比如

这是获取价格的方法,返回一个 double 代表价格。就算 double 可以保证计算精度,这里也还可以进一步优化,比如,经常要求商品价格是大于0的,所以会有下面的逻辑

这就是因为 double 作为基本类型并没有 价格大于0 的方法。

Java8 Lambda如何高效构建多层嵌套Map?

这里的解决办法,就是 Replace Primitive with Object ,以对象取代基本类型。

甚至有人认为需要封装所有的基本类型和字符串,并且使用一流的集合。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

本文共计1253个文字,预计阅读时间需要6分钟。

Java8 Lambda如何高效构建多层嵌套Map?

目录 + 使用Lambda快速生成map、多层嵌套map + List转换为Map(id, bean) + 一主多子javaBean List转换为Map(id, Map(id, itemBean)) + 常见代码异味——多层嵌套,缺乏封装 1. 多层嵌套 2. 缺乏封装,利用Lambda快速生成

目录
  • 利用Lambda快速生成map、多层嵌套map
    • List 转为 Map<id, bean>
    • 一主多子 javaBean List 转为 Map<id, Map<id, itemBean> >
  • 常见的代码坏味道--多层嵌套,缺乏封装
    • 1. 多层嵌套
    • 2. 缺乏封装

利用Lambda快速生成map、多层嵌套map

List 转为 Map<id, bean>

  • User是List对象的元素,List
  • List对象的变量名为:userList
  • id 将作为 Map 的 Key

Map<String, User> idMap = userList.stream().collect( Collectors.toMap(User::getId, b->b) );

一主多子 javaBean List 转为 Map<id, Map<id, itemBean> >

  • 一主,主Bean: User
  • 多子,子Bean: UserItem
  • 集合:List
  • 转Map:Map<User_id, Map <UserItem_id, UserItem> >

一主多子的主javaBean为List对象的元素,List

此处List对象的变量为:userList

Map<String, Map<String, UserItem>> collect =      userList.stream().collect(         Collectors.toMap(             User::getId, b -> {                 return b.getUserItem().stream().collect(                         Collectors.toMap(UserItem::getId, c -> c)                 );             }         )     );

常见的代码坏味道--多层嵌套,缺乏封装

1. 多层嵌套

多层嵌套的两个原因

1.1if else

最简单的重构手法,提前 return ,也叫 Replace Nested Conditional with Guard Clauses 卫语句。

有一些比较激进的看法认为 else 本身就是一种坏味道。

可以使用 idea 的插件 Checkstyle 检查一下代码的 圈复杂度。当圈复杂度大于某个值的时候,就会报错。

圈复杂度的这部分代码中线性无关路径的数量。

如果一段源码中不包含控制流语句(条件或决策点),那么这段代码的圈复杂度为1,因为这段代码中只会有一条路径;如果一段代码中仅包含一个if语句,且if语句仅有一个条件,那么这段代码的圈复杂度为2;包含两个嵌套的if语句,或是一个if语句有两个条件的代码块的圈复杂度为3。

第二种解决过多判断的方案是多态,这就要求从设计阶段就开始考虑实现方案。

注意多态的本质是想要实现对拓展开发,对修改关闭,所以如果继承的层级较多,逻辑比较复杂,就会导致适得其反的效果。

1.2 for 循环

对集合进行循环操作推荐使用java8的Stream操作(,mapreduce,map代表操作,collect代表reduce),比如。从本质上讲Stream也是循环,但是这种语法糖的形式会对各种操作进行分类,进行合理的优化处理。

循环和函数式编程的区别不仅仅在写法上,更体现在思想上。前者描述实现细节,后者描述做什么。

当然,如果在列表转换中使用过多的 lambda 表达式,会导致看起来很吃力,不好理解。这时候长的lambda本身可以提取成为方法。

2. 缺乏封装

2.1. 过长的消息链或者说火车残骸

第一种缺乏封装的表现是java类处理不当,可能是设计的太粗糙,面向过程实现业务逻辑导致的。这就要求开发的时候进行更多的抽象。

比如,不是所有的java类都直接提供所有的getter setter 方法就行,还要根据业务场景进行合理选择;另外对象内部的细节不需要过多的暴露出去,应该做适当的封装。

2.2 基本类型的偏执

第二种更高级的缺乏封装,是指用基本类型代表所有的业务数据。比如

这是获取价格的方法,返回一个 double 代表价格。就算 double 可以保证计算精度,这里也还可以进一步优化,比如,经常要求商品价格是大于0的,所以会有下面的逻辑

这就是因为 double 作为基本类型并没有 价格大于0 的方法。

Java8 Lambda如何高效构建多层嵌套Map?

这里的解决办法,就是 Replace Primitive with Object ,以对象取代基本类型。

甚至有人认为需要封装所有的基本类型和字符串,并且使用一流的集合。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。