在java开发中,我们经常需要对数据结构进行转换以适应不同的业务需求。假设我们有一个map
Map> map = new HashMap<>(); map.put("projectA", Arrays.asList(new User(1,"Bob"), new User(2,"John"), new User(3,"Mo"))); map.put("projectB", Arrays.asList(new User(2,"John"), new User(3,"Mo"))); map.put("projectC", Arrays.asList(new User(3,"Mo")));
我们的目标是将这个Map转换为Map
Bob = [projectA] John = [projectA, projectB] Mo = [projectA, projectB, projectC]
这本质上是将一个“项目-用户”的多对一关系,反向转换为“用户-项目”的一对多关系。
为了更好地表示用户,我们首先定义一个User类。在Java 16及以上版本中,可以使用record来简洁地定义不可变的数据类。
public record User(int id, String name) {}如果使用Java 8-15,你需要定义一个普通的类,并确保正确实现equals()和hashCode()方法,这对于将User对象用作Map的键至关重要。
// Java 8-15 示例
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() { return id; }
public String getName() { return name; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "User[id=" + id + ", name=" + name + "]";
}
}最直接的解决方案是使用嵌套循环遍历原始Map的每个条目及其内部的用户列表。
实现思路:
sent()方法将该用户作为键,并初始化一个空的ArrayList代码示例:
import java.util.*;
import java.util.stream.Collectors;
public class MapTransformation {
// User record (Java 16+)
public static record User(int id, String name) {}
public static void main(String[] args) {
Map> projectUserMap = new HashMap<>();
projectUserMap.put("projectA", Arrays.asList(new User(1,"Bob"), new User(2,"John"), new User(3,"Mo")));
projectUserMap.put("projectB", Arrays.asList(new User(2,"John"), new User(3,"Mo")));
projectUserMap.put("projectC", Arrays.asList(new User(3,"Mo")));
Map> userProjectMap = new HashMap<>();
for (Map.Entry> entry : projectUserMap.entrySet()) {
String projectName = entry.getKey();
List users = entry.getValue();
for (User user : users) {
// 如果用户不在结果Map中,则为其创建一个新的项目列表
userProjectMap.putIfAbsent(user, new ArrayList<>());
// 将当前项目添加到该用户的项目列表中
userProjectMap.get(user).add(projectName);
}
}
System.out.println("传统迭代法结果:");
System.out.println(userProjectMap);
}
} 输出示例:
传统迭代法结果:
{User[id=1, name=Bob]=[projectA], User[id=2, name=John]=[projectA, projectB], User[id=3, name=Mo]=[projectA, projectB, projectC]}Java 8引入的Stream API提供了一种更函数式和声明式的方式来处理集合数据。通过结合flatMap和Collectors.groupingBy,我们可以实现相同的转换,代码通常更简洁。
实现思路:
代码示例:
import java.util.*;
import java.util.stream.Collectors;
public class MapTransformationStream {
public static record User(int id, String name) {}
public static void main(String[] args) {
Map> projectUserMap = new HashMap<>();
projectUserMap.put("projectA", Arrays.asList(new User(1,"Bob"), new User(2,"John"), new User(3,"Mo")));
projectUserMap.put("projectB", Arrays.asList(new User(2,"John"), new User(3,"Mo")));
projectUserMap.put("projectC", Arrays.asList(new User(3,"Mo")));
Map> userProjectMapStream = projectUserMap.entrySet().stream()
.flatMap(entry -> entry.getValue().stream() // 扁平化用户列表
.map(user -> Map.entry(user, entry.getKey()))) // 为每个用户创建 (用户, 项目名) 对
.collect(Collectors.groupingBy(
Map.Entry::getKey, // 以User作为分组键
Collectors.mapping(Map.Entry::getValue, Collectors.toList()) // 将项目名收集到List中
));
System.out.println("Stream API法结果:");
System.out.println(userProjectMapStream);
}
} 输出示例:
Stream API法结果:
{User[id=1, name=Bob]=[projectA], User[id=2, name=John]=[projectA, projectB], User[id=3, name=Mo]=[projectA, projectB, projectC]}本教程展示了两种在Java中将Map