当前位置: 首页 > news >正文

做物流网站模块模板建设网站

做物流网站模块,模板建设网站,网站如何添加统计代码,哈尔滨seo优化排名免费咨询🚀 深入解析 Java Stream API:从 List 到 Map 的优雅转换 🔧 大家好!👋 今天我们来聊聊 Java 8 中一个非常常见的操作:使用 Stream API 将 List 转换为 Map。🎉 具体来说,我们将深入…

🚀 深入解析 Java Stream API:从 ListMap 的优雅转换 🔧

大家好!👋 今天我们来聊聊 Java 8 中一个非常常见的操作:使用 Stream API 将 List 转换为 Map。🎉 具体来说,我们将深入分析以下代码片段:

Map<Integer, InviteCode> inviteCodeMap = inviteCodes.stream().collect(Collectors.toMap(InviteCode::getId, ic -> ic));

这段代码看似简单,但背后涉及了 Stream API、方法引用、Lambda 表达式以及 Collectors.toMap 的强大功能。💡 我们将从代码的背景开始,逐步拆解它的实现原理,探讨使用场景、优势和优化方法,最后通过一个实际案例展示它的应用。为了更直观地理解整个过程,我们还会插入一个 Mermaid 流程图!📊

准备好了吗?让我们开始吧!🚀


📖 背景:为什么需要将 List 转换为 Map

在 Java 开发中,我们经常需要处理集合数据。例如,在一个邀请码系统中,我们有一个 List<InviteCode>,其中 InviteCode 是一个实体类,包含 idinviteCodeinviteLevelcreatedBy 等字段:

public class InviteCode {private Integer id;private String inviteCode;private Integer inviteLevel;private Integer createdBy;// Getters and Setterspublic Integer getId() {return id;}public String getInviteCode() {return inviteCode;}public Integer getInviteLevel() {return inviteLevel;}public Integer getCreatedBy() {return createdBy;}
}

假设我们有一个 List<InviteCode>,包含 adminId = 7 的所有邀请码记录:

idadmin_idcreated_byinvite_codeinvite_level
207NULL******0
217202631131
227207043581
237209828681
247NULL******0
25724******1
26725******2
277269914763

我们的目标是构建一个以 adminId 为根的邀请码层级树。为了高效地查找某个 id 对应的 InviteCode 对象,我们需要将 List<InviteCode> 转换为 Map<Integer, InviteCode>,其中:

  • 键(Key)InviteCodeidInteger 类型)。
  • 值(Value)InviteCode 对象本身。

这就是以下代码的作用:

Map<Integer, InviteCode> inviteCodeMap = inviteCodes.stream().collect(Collectors.toMap(InviteCode::getId, ic -> ic));

🌟 代码拆解:一步步理解

让我们逐步拆解这段代码,弄清楚它是如何工作的!

1. inviteCodes.stream()

  • inviteCodes:是一个 List<InviteCode>,包含 adminId = 7 的 8 条记录(id = 20, 21, ..., 27)。
  • stream():将 List<InviteCode> 转换为一个 Stream<InviteCode>
    • Stream 是 Java 8 引入的流式 API,允许你以声明式的方式处理集合数据(例如映射、过滤、归约等)。

结果inviteCodes.stream() 生成了一个 Stream<InviteCode>,包含 8 个 InviteCode 对象。

2. .collect(Collectors.toMap(...))

  • collect:是 Stream 的终止操作,用于将流中的元素收集到一个结果容器中(例如 ListSetMap)。
  • Collectors.toMap:是一个收集器(Collector),专门用于将流中的元素收集到一个 Map 中。
Collectors.toMap 的方法签名
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper
)
  • 参数
    • keyMapper:一个函数,用于从流中的每个元素提取 Map 的键(Key)。
    • valueMapper:一个函数,用于从流中的每个元素提取 Map 的值(Value)。
  • 返回值:一个 Map<K, U>

在我们的代码中:

  • TInviteCode(流中的元素类型)。
  • KInteger(键的类型)。
  • UInviteCode(值的类型)。

3. InviteCode::getId

  • InviteCode::getId:这是一个方法引用(Method Reference),等价于 Lambda 表达式 ic -> ic.getId()
  • 作用:从 InviteCode 对象中提取 id 字段,作为 Map 的键。
  • 类型Function<InviteCode, Integer>,将 InviteCode 映射为 Integer

示例

  • 如果 InviteCode 对象的 id20InviteCode::getId 会返回 20

4. ic -> ic

  • ic -> ic:这是一个 Lambda 表达式,表示一个简单的映射函数。
  • 作用:将 InviteCode 对象本身作为 Map 的值。
  • 类型Function<InviteCode, InviteCode>,将 InviteCode 映射为它自己。

示例

  • 如果 InviteCode 对象是 icid = 20),ic -> ic 直接返回这个 ic 对象。

5. 整体效果

  • Collectors.toMap(InviteCode::getId, ic -> ic)
    • Stream<InviteCode> 中的每个 InviteCode 对象:
      • 使用 InviteCode::getId 提取 id 作为键。
      • 使用 ic -> ic 提取整个 InviteCode 对象作为值。
    • 将所有键值对收集到一个 Map<Integer, InviteCode> 中。

结果

  • inviteCodeMap 是一个 Map<Integer, InviteCode>,其中:
    • inviteCodeMap.get(20)InviteCode(id=20, inviteCode="******", ...)
    • inviteCodeMap.get(21)InviteCode(id=21, inviteCode="263113", ...)
    • inviteCodeMap.get(27)InviteCode(id=27, inviteCode="991476", ...)

📊 Mermaid 流程图:可视化转换过程

为了更直观地理解 List<InviteCode>Map<Integer, InviteCode> 的转换过程,我们使用 Mermaid 流程图来展示:

Start: List<InviteCode>
inviteCodes
Stream<InviteCode>
inviteCodes.stream()
For each InviteCode in Stream
Extract Key:
InviteCode::getId
(e.g., id = 20)
Extract Value:
ic -> ic
(e.g., InviteCode object)
Key-Value Pair:
(20, InviteCode(id=20, ...))
Collect to Map<Integer, InviteCode>
Collectors.toMap()
End: Map<Integer, InviteCode>
inviteCodeMap
  • 流程说明
    1. List<InviteCode> 开始,转换为 Stream<InviteCode>
    2. 对流中的每个 InviteCode 对象:
      • 使用 InviteCode::getId 提取键(id)。
      • 使用 ic -> ic 提取值(InviteCode 对象)。
    3. 将所有键值对收集到 Map<Integer, InviteCode> 中。

🌟 为什么需要 inviteCodeMap

在邀请码系统中,我们的目标是构建一个以 adminId 为根的层级树。为了高效地查找某个 id 对应的 InviteCode 对象,我们需要将 List<InviteCode> 转换为 Map<Integer, InviteCode>

1. 后续代码

// 找到所有根节点(createdBy = NULL)
List<InviteCode> roots = inviteCodes.stream().filter(ic -> ic.getCreatedBy() == null).collect(Collectors.toList());// 为每个根节点构建树形结构
List<InviteCodeTreeDTO> trees = new ArrayList<>();
for (InviteCode root : roots) {InviteCodeTreeDTO tree = buildTree(root, inviteCodeMap, new HashSet<>());trees.add(tree);
}

buildTree 方法中,需要根据 createdBy 查找子节点:

private InviteCodeTreeDTO buildTree(InviteCode root, Map<Integer, InviteCode> inviteCodeMap, Set<Integer> visited) {if (!visited.add(root.getId())) {throw new IllegalStateException("Detected a cycle in invite code hierarchy at ID: " + root.getId());}InviteCodeTreeDTO node = new InviteCodeTreeDTO();node.setId(root.getId());node.setInviteCode(root.getInviteCode());node.setInviteLevel(root.getInviteLevel());node.setChildren(new ArrayList<>());// 查找所有子节点(createdBy = root.id)List<InviteCode> children = inviteCodeMap.values().stream().filter(ic -> Objects.equals(ic.getCreatedBy(), root.getId())).collect(Collectors.toList());for (InviteCode child : children) {InviteCodeTreeDTO childNode = buildTree(child, inviteCodeMap, new HashSet<>(visited));node.getChildren().add(childNode);}return node;
}
  • 为什么用 Map
    • 如果直接遍历 inviteCodes 查找子节点(createdBy = root.id),时间复杂度是 O(n)
    • 使用 inviteCodeMap,可以通过 id 直接查找 InviteCode 对象,时间复杂度是 O(1)(尽管当前 children 查找仍需优化)。

🚀 优势:为什么使用 Stream API?

1. 代码简洁

  • Stream API 提供了声明式的写法,比传统的 for 循环更简洁。
  • 传统写法可能需要手动遍历和填充 Map
    Map<Integer, InviteCode> inviteCodeMap = new HashMap<>();
    for (InviteCode ic : inviteCodes) {inviteCodeMap.put(ic.getId(), ic);
    }
    
  • 使用 Stream API,代码更简洁优雅。

2. 功能强大

  • Stream API 支持链式操作,可以轻松添加过滤、映射等操作。
  • 例如,如果只想收集 inviteLevel > 0InviteCode
    Map<Integer, InviteCode> inviteCodeMap = inviteCodes.stream().filter(ic -> ic.getInviteLevel() > 0).collect(Collectors.toMap(InviteCode::getId, ic -> ic));
    

3. 并行处理

  • Stream API 支持并行处理(parallelStream()),在大规模数据下可以提高性能:
    Map<Integer, InviteCode> inviteCodeMap = inviteCodes.parallelStream().collect(Collectors.toMap(InviteCode::getId, ic -> ic));
    

🛠️ 优化建议

1. 更高效的子节点查找

当前 buildTree 方法中,查找子节点的方式可以通过 inviteCodeMap 进一步优化:

// 预先构建 createdBy 到子节点的映射
Map<Integer, List<InviteCode>> childrenMap = inviteCodes.stream().filter(ic -> ic.getCreatedBy() != null).collect(Collectors.groupingBy(InviteCode::getCreatedBy));// 修改 buildTree 方法
private InviteCodeTreeDTO buildTree(InviteCode root, Map<Integer, InviteCode> inviteCodeMap, Map<Integer, List<InviteCode>> childrenMap, Set<Integer> visited) {if (!visited.add(root.getId())) {throw new IllegalStateException("Detected a cycle in invite code hierarchy at ID: " + root.getId());}InviteCodeTreeDTO node = new InviteCodeTreeDTO();node.setId(root.getId());node.setInviteCode(root.getInviteCode());node.setInviteLevel(root.getInviteLevel());node.setChildren(new ArrayList<>());// 查找所有子节点(createdBy = root.id)List<InviteCode> children = childrenMap.getOrDefault(root.getId(), Collections.emptyList());for (InviteCode child : children) {InviteCodeTreeDTO childNode = buildTree(child, inviteCodeMap, childrenMap, new HashSet<>(visited));node.getChildren().add(childNode);}return node;
}
  • 效果:通过 childrenMap,可以以 O(1) 的时间复杂度找到某个 id 的所有子节点。

2. 处理键冲突

Collectors.toMap 默认情况下,如果有重复的键(id),会抛出 IllegalStateException: Duplicate key。在我们的场景中,id 是主键,应该不会有重复,但为了安全起见,可以指定合并策略:

Map<Integer, InviteCode> inviteCodeMap = inviteCodes.stream().collect(Collectors.toMap(InviteCode::getId,ic -> ic,(existing, replacement) -> existing // 如果有重复的 id,保留第一个));
  • 效果:如果 id 重复,保留第一个 InviteCode 对象。

📝 完整代码:实际应用

以下是完整的 InviteCodeService 实现,展示了如何使用 inviteCodeMap 构建层级树:

public class InviteCodeService {private final InviteCodeRepository inviteCodeRepository;public InviteCodeService(InviteCodeRepository inviteCodeRepository) {this.inviteCodeRepository = inviteCodeRepository;}public AdminInviteCodeTreeDTO getAdminInviteCodeTree(Integer adminId) {List<InviteCode> inviteCodes = inviteCodeRepository.findByAdminId(adminId);if (inviteCodes.isEmpty()) {AdminInviteCodeTreeDTO result = new AdminInviteCodeTreeDTO();result.setAdminId(adminId);result.setChildren(Collections.emptyList());return result;}// 将 List<InviteCode> 转换为 Map<Integer, InviteCode>Map<Integer, InviteCode> inviteCodeMap = inviteCodes.stream().collect(Collectors.toMap(InviteCode::getId, ic -> ic));// 预构建 createdBy 到子节点的映射Map<Integer, List<InviteCode>> childrenMap = inviteCodes.stream().filter(ic -> ic.getCreatedBy() != null).collect(Collectors.groupingBy(InviteCode::getCreatedBy));// 找到所有根节点(createdBy = NULL)List<InviteCode> roots = inviteCodes.stream().filter(ic -> ic.getCreatedBy() == null).collect(Collectors.toList());// 为每个根节点构建树形结构List<InviteCodeTreeDTO> trees = new ArrayList<>();for (InviteCode root : roots) {InviteCodeTreeDTO tree = buildTree(root, inviteCodeMap, childrenMap, new HashSet<>());trees.add(tree);}AdminInviteCodeTreeDTO result = new AdminInviteCodeTreeDTO();result.setAdminId(adminId);result.setChildren(trees);return result;}private InviteCodeTreeDTO buildTree(InviteCode root, Map<Integer, InviteCode> inviteCodeMap, Map<Integer, List<InviteCode>> childrenMap, Set<Integer> visited) {if (!visited.add(root.getId())) {throw new IllegalStateException("Detected a cycle in invite code hierarchy at ID: " + root.getId());}InviteCodeTreeDTO node = new InviteCodeTreeDTO();node.setId(root.getId());node.setInviteCode(root.getInviteCode());node.setInviteLevel(root.getInviteLevel());node.setChildren(new ArrayList<>());List<InviteCode> children = childrenMap.getOrDefault(root.getId(), Collections.emptyList());for (InviteCode child : children) {InviteCodeTreeDTO childNode = buildTree(child, inviteCodeMap, childrenMap, new HashSet<>(visited));node.getChildren().add(childNode);}return node;}
}

🎉 总结

通过 Stream API 和 Collectors.toMap,我们可以轻松地将 List<InviteCode> 转换为 Map<Integer, InviteCode>,为后续的层级树构建提供了高效的数据结构。💻

  • 核心代码inviteCodes.stream().collect(Collectors.toMap(InviteCode::getId, ic -> ic)) 将列表转换为映射。
  • 优势:代码简洁、功能强大、支持并行处理。
  • 优化:通过 childrenMap 提高子节点查找效率,处理键冲突。

希望这篇博客对你理解 Stream API 和 Collectors.toMap 有所帮助!💬 如果你有其他问题,欢迎留言讨论!🚀

📚 参考:Java 官方文档、Collectors 源码。点赞和分享哦!😊

在这里插入图片描述

http://www.dtcms.com/a/472266.html

相关文章:

  • 网站备案截图昆山手机网站建设公司
  • 学校网站设计的目的用固定ip做访问网站服务器
  • 替老外做网站自己办网站
  • 长治县网站建设wordpress 自动 图片大小
  • 大连龙彩科技的网站在谁家做海南高端建设网站
  • 谷德设计网站桂林市临桂区城乡建设局网站
  • 从太敏原始遥测值计算太阳矢量(卫星本体系)详解
  • 网站名查找expression wordpress主题
  • dede网站本地访问速度慢鞍山人才网档案查询
  • 淘宝网站开发者wordpress添加短代码
  • 网站建设项目表网站怎么做推广和优化
  • 耄大厨——AI厨师智能体(2-RAG知识库)
  • 网站建设费用包括哪些内容在线p图修改文字
  • 专业做网站建wordpress临时关闭
  • 商城网站建设策划酒店网站建设 源码
  • 张家港网站建设服务朝青板块网站建设
  • 没有后台的网站怎么做排名国外好的网页设计
  • 网站是如何设计配置方案的济南网站建设价格
  • 网站建设维护费 会计科目电商网站建设开发公司
  • vue网站开发为什么收不到自己网站
  • 蓬莱网站建设联系电话中山建设厅网站
  • 罗湖商城网站建设找哪家公司比较安全WordPress搜索结果文字修改
  • 网站建设和维护工作总结有赞微商城怎么开店
  • 今天建设银行网站无法登录主机wordpress
  • 查询网站备案时间中山网站快照优化公司
  • 长沙优秀网站建设超链接友情外链查询
  • 免费提供网站聊天软件
  • 嘉兴网站制作策划wordpress 邮箱订阅
  • 网站怎么做百度地图市场营销策略都有哪些
  • 天津企业网络建站大连网站制作优选ls15227