如何用 Stream API 替换嵌套循环

How can I replace the nested loops with Stream API

是否可以将下面代码中的嵌套循环替换为 Stream API?

Map<String, List<Role>> roleByUserUsername = roles.stream()
    .collect(Collectors.groupingBy(//some foo that return userName
                Role::getRoleId,
                Collectors.toList()));

List<User> users = List.of(new User(), new User());
HashMap<String, User> userByRoleId = new HashMap<>();

for (final User user : users) {
    for (final Role roles1 : roleByUserUsername.get(user.getPassword())) {
        userByRoleId.put(roles1.getRoleId(), user);
    }
}

试试这个

users.stream().forEach(user->roleByUserUsername.get(user.getPassword()).forEach(role->userByRoleId.put(role.getRoleId(), user)));

您需要展平从地图roleByUsername获得的角色列表。

顺便说一句,有一个不一致的地方:根据它的名字,map 意味着包含 usernames作为 keys,但在循环中,您通过提供调用 getPassword().

返回的结果来访问它

然后您需要应用 collect 作为终端操作并提供收集器 toMap() 作为参数以生成将 roleId 与单个 [=47= 相关联的映射]用户.

List<Role> roles = // initialing the list of roles
    
Map<String, List<Role>> roleByUsername = roles.stream()
    .collect(Collectors.groupingBy(Role::getRoleId));
    
List<User> users = List.of(new User(), new User());
        
Map<String, User> userByRoleId = users.stream()
    .flatMap(user -> roleByUsername.get(user.getPassword()).stream()
                .map(role -> Map.entry(role.getRoleId(), user)))
    .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue
            ));

但是这里有一个逻辑问题。假设 roleId 对于每个角色都是唯一的,但是可以有多个用户具有相同的角色。除非您设计了一个应用程序,其中每个 用户 都有一个唯一的 角色

因此,将映射类型更改为 Map<String, List<User>> 是有意义的,这样 user 的集合将映射到每个 roleId

为此,我们需要将收集器从 toMap 更改为 groupingBy() 以及 mapping()toList()

Map<String, List<User>> userByRoleId = users.stream()
    .flatMap(user -> roleByUsername.get(user.getPassword()).stream()
                .map(role -> Map.entry(role.getRoleId(), user)))
    .collect(Collectors.groupingBy(
                Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue,
                    Collectors.toList())
            ));

旁注:

  • Collector groupingBy() 有一种风格,它只需要一个参数 - classifier function。默认情况下,它会将映射到相同 key 的所有元素存储到列表中。您不需要提供 toList() 作为下游。

  • 针对 Map 等接口编写代码,不要使其依赖于具体实现:What does it mean to "program to an interface"?