讲师中心 微信公众号
AI工具推荐 视频效率加速

Java数据结构转换:从项目-用户映射到用户-项目映射

风萱姑娘_9928

风萱姑娘_9928

发布时间:2025-09-19 12:33:05

|

441人浏览过

|

来源于php中文网

原创

Java数据结构转换:从项目-用户映射到用户-项目映射

本教程详细介绍了如何在Java中将一个Map<String, List<User>>(项目到用户列表的映射)数据结构转换为Map<User, List<String>>(用户到项目列表的映射)。通过迭代原始映射的条目,并利用putIfAbsent方法高效地构建新的映射,实现用户与相关项目列表的精确关联,从而满足特定数据重组需求。

1. 问题描述与目标

在实际开发中,我们经常需要对数据结构进行转换以适应不同的业务逻辑或查询需求。假设我们有一个map<string, list<user>>类型的数据,其中键(string)代表项目名称,值(list<user>)代表与该项目关联的用户列表。例如:

Map<String, List<User>> projectToUsersMap = new HashMap<>();
projectToUsersMap.put("projectA", Arrays.asList(new User(1,"Bob"), new User(2,"John"), new User(3,"Mo")));
projectToUsersMap.put("projectB", Arrays.asList(new User(2,"John"), new User(3,"Mo")));
projectToUsersMap.put("projectC", Arrays.asList(new User(3,"Mo")));

我们的目标是将这个映射转换为Map<User, List<String>>类型,其中键(User)代表一个独立的用户,值(List<String>)代表该用户所参与的所有项目名称列表。期望的输出效果如下:

Bob  = [projectA]
John = [projectA, projectB]
Mo   = [projectA, projectB, projectC]

这种转换在需要根据用户查询其参与项目列表的场景中非常有用。

2. 核心实现思路

实现这一转换的核心思路是遍历原始映射中的每一个条目(Entry),然后针对每个条目,再遍历其值(即用户列表)。对于遍历到的每一个用户,我们需要将其作为新映射的键,并将当前项目的名称添加到该用户对应的项目列表中。

具体步骤如下:

立即学习“Java免费学习笔记(深入)”;

  1. 创建一个新的Map<User, List<String>>来存储转换后的结果。
  2. 遍历原始projectToUsersMap的每一个Map.Entry<String, List<User>>。
    • String是当前的项目名称。
    • List<User>是当前项目下的用户列表。
  3. 对于每个Map.Entry,获取其键(项目名称)和值(用户列表)。
  4. 遍历当前项目下的每一个User对象。
    • 在新映射中,检查当前User是否已存在作为键。
    • 如果不存在,则使用putIfAbsent(user, new ArrayList<>())方法将该用户添加为键,并为其创建一个新的空项目列表。
    • 无论用户是否已存在,都通过get(user).add(projectName)方法将当前项目名称添加到该用户对应的项目列表中。

3. Java代码示例

以下是实现上述转换的完整Java代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class UserProjectMapper {

    // 定义User记录类,自动生成equals(), hashCode(), toString()
    public static record User(int id, String name) {}

    public static void main(String[] args) {
        // 原始数据:项目到用户列表的映射
        Map<String, List<User>> projectToUsersMap = new HashMap<>();
        projectToUsersMap.put("projectA", Arrays.asList(new User(1,"Bob"), new User(2,"John"), new User(3,"Mo")));
        projectToUsersMap.put("projectB", Arrays.asList(new User(2,"John"), new User(3,"Mo")));
        projectToUsersMap.put("projectC", Arrays.asList(new User(3,"Mo")));

        // 用于存储转换结果的新映射:用户到项目列表的映射
        Map<User, List<String>> userToProjectsMap = new HashMap<>();

        // 遍历原始映射的每个条目
        for (Map.Entry<String, List<User>> entry : projectToUsersMap.entrySet()) {
            String projectName = entry.getKey(); // 获取当前项目名称
            List<User> usersInProject = entry.getValue(); // 获取当前项目下的用户列表

            // 遍历当前项目下的每个用户
            for (User user : usersInProject) {
                // 如果用户在新映射中不存在,则为其创建一个新的项目列表
                userToProjectsMap.putIfAbsent(user, new ArrayList<>());
                // 将当前项目名称添加到该用户对应的项目列表中
                userToProjectsMap.get(user).add(projectName);
            }
        }

        // 打印转换后的结果
        System.out.println("转换后的映射 (User -> List<String>):");
        userToProjectsMap.forEach((user, projects) -> 
            System.out.println(user.name() + " = " + projects)
        );
        // 打印完整的Map对象
        System.out.println("\n完整的Map对象表示:");
        System.out.println(userToProjectsMap);
    }
}

4. 代码解析

  1. public static record User(int id, String name) {}:

    • 这里使用了Java 16+ 引入的 record 类型来定义 User。record 是一种紧凑的类声明,它自动为我们生成了构造函数、访问器方法(id()和name())、equals()、hashCode()和toString()方法。
    • 重要性:当自定义对象(如User)作为Map的键时,正确实现equals()和hashCode()方法至关重要。HashMap依赖这两个方法来判断两个键是否相等以及如何存储和查找键。record类型自动处理了这一点,确保了具有相同id和name的User对象被视为同一个键。如果使用普通的class,则需要手动重写这些方法。
  2. Map<User, List<String>> userToProjectsMap = new HashMap<>();:

    Java Maven Code Review
    Java Maven Code Review

    审查Java Maven项目(ZIP压缩包或GitLab仓库URL),检查代码规范、命名、模块边界、可维护性问题以及重复代码。

    下载
    • 初始化一个空的HashMap,用于存储最终的用户到项目列表的映射。
  3. 外层循环 for (Map.Entry<String, List<User>> entry : projectToUsersMap.entrySet()):

    • 遍历原始projectToUsersMap的键值对。entry.getKey()获取项目名称(String),entry.getValue()获取该项目对应的用户列表(List<User>)。
  4. 内层循环 for (User user : usersInProject):

    • 遍历当前项目下的每一个User对象。
  5. userToProjectsMap.putIfAbsent(user, new ArrayList<>());:

    • 这是实现逻辑的关键一步。putIfAbsent(K key, V value)方法会检查userToProjectsMap中是否已经存在user这个键。
      • 如果不存在,它会将user作为键,并将一个新创建的ArrayList<String>作为值放入映射中。
      • 如果已经存在,它不会做任何操作,保留原有的值(即该用户已有的项目列表)。
    • 这个方法确保了每个用户只对应一个项目列表,并且在第一次遇到某个用户时为其初始化列表。
  6. userToProjectsMap.get(user).add(projectName);:

    • 获取当前用户user对应的项目列表。由于putIfAbsent的保证,我们知道这里获取到的列表一定是非null的。
    • 将当前的项目名称projectName添加到该用户的项目列表中。

5. 运行结果

执行上述代码,将得到以下输出:

转换后的映射 (User -> List<String>):
Bob = [projectA]
John = [projectA, projectB]
Mo = [projectA, projectB, projectC]

完整的Map对象表示:
{User[id=1, name=Bob]=[projectA], User[id=2, name=John]=[projectB, projectA], User[id=3, name=Mo]=[projectB, projectA, projectC]}

这完美地实现了将项目到用户的映射转换为用户到项目的映射,每个用户都关联了其参与的所有项目。

6. 总结

本教程展示了如何通过迭代和条件插入(putIfAbsent)的方式,将一个复杂的嵌套Map数据结构高效地转换为另一种满足特定查询需求的数据结构。理解并正确运用Map的equals()和hashCode()方法(或使用record类型自动处理)是处理自定义对象作为Map键的关键。这种数据重构技术在处理多对多关系的数据时非常实用,有助于简化后续的数据查询和业务逻辑实现。

热门AI工具

更多
SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

5719

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

529

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1678

2024.03.01

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

5719

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2845

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

3568

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2525

2025.08.29

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2341

2023.12.01

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

80

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn