我有一个
Map<String,List<User>>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")));
可以用String代替User。
字符串是一个项目名称,但是相同的用户可以关联到不同的项目。
我想得到像Map<User, List<String>>
这样的东西,其中键将表示一个不同的用户和一个值,作为与他/她相关的项目名称的列表。
Bob = [projectA]
John = [projectA, projectB]
Mo = [projectA, projectB, projectC]
对于任何建议都要提前TQ。
循环遍历map的条目和其中的List:
public static void main(String[] args) {
Map<String, List<User>> 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<User, List<String>> result = new HashMap<>();
for(Map.Entry<String, List<User>> e:map.entrySet()) {
for(User u:e.getValue()) {
result.putIfAbsent(u, new ArrayList<>());
result.get(u).add(e.getKey());
}
}
System.out.println(result);
}
public static record User(int id, String name) {}
打印
{User[id=1, name=Bob]=[projectA], User[id=2, name=John]=[projectB, projectA], User[id=3, name=Mo]=[projectB, projectA, projectC]}
要反转这个Map,您需要遍历它的条目,并为每个不同的用户创建一个包含项目列表的条目,作为结果Map中的值。
Java 8 computeIfAbsent()
这个逻辑可以用Java 8方法Map.computeIfAbsent()
和Map.forEach()
来实现。
Map<String, List<User>> usersByProject = // initilizing the source map
Map<User, List<String>> projectsByUser = new HashMap<>();
usersByProject.forEach((project, users) ->
users.forEach(user -> projectsByUser.computeIfAbsent(user, k -> new ArrayList<>())
.add(project))
);
<标题>流API h1> 于流的实现需要更多的努力。
核心逻辑保持不变。但是有一个重要的特性:我们需要从源Map的每个条目生成一个新元素序列,其中包含对特定用户和项目的引用。
为了携带这些数据,我们需要一个辅助类型,Java 16记录非常适合这个角色。另一种快速而肮脏的方法是使用Map.Entry
,但最好避免使用这种方法,因为方法getKey()
/getValue()
是不公开的,需要更多的努力来推断代码。如果你使用的是早期版本的JDK,你也可以定义一个常规的class
。
public record UserProject(User user, String project) {}
这就是基于流的解决方案的样子:
Map<String, List<User>> usersByProject = Map.of(
"projectA", List.of(new User(1, "Bob"), new User(2, "John"), new User(3, "Mo")),
"projectB", List.of(new User(2, "John"), new User(3, "Mo")),
"projectC", List.of(new User(3, "Mo"))
);
Map<User, List<String>> projectByUsers = usersByProject.entrySet().stream()
.flatMap(entry -> entry.getValue().stream().
map(user -> new UserProject(user, entry.getKey()))
)
.collect(Collectors.groupingBy(
UserProject::user,
Collectors.mapping(UserProject::project,
Collectors.toList())
));
projectsByUser.forEach((k, v) -> System.out.println(k + " -> " + v));
输出:
User[id=1, name=Bob] -> [projectA]
User[id=2, name=John] -> [projectA, projectB]
User[id=3, name=Mo] -> [projectA, projectC, projectB]
标题>