使用对象中的值准备列表映射,其中键是此对象内列表中的值

Prepare map of list with values from object where key is value from list inside this object

我class喜欢:

public class User {
   private Long id;
   private String firstname;
   private String lastname;
   private Address address;
   private boolean active;
   private List<Country> countries;
}

public class Country {
  private String name;
  private String capital;
}

而且我需要按国家/地区名称对用户进行排序。我做了这样的事情:

        final Map<String, List<UserHelper>> usersByCountry = new HashMap<>();

        users.stream()
                .filter(User::isActive)
                .forEach(user -> user.getCountry().stream()
                        .map(Country::getName)
                        .forEach(name -> {
                            if (usersByCountry.containsKey(name)) {
                                usersByCountry.get(name).add(new UserHelper(user.getId(), user.getFirstname()));
                            } else {
                                usersByCountry.put(name, new ArrayList<>(List.of(new UserHelper(user.getId(), user.getFirstname()))));
                            }
                        }));

    @Value
    private class UserHelper {
        Long id;
        String firstname;
    }

但我想避免在 foreach 中添加要映射的元素。我更喜欢 Collectors.toMap()groupingBy 之类的东西,但我不知道如何在这个地方做到这一点。

如果我没有正确理解你的问题,你想按国家/地区对用户进行分组。由于一个用户可以有多个国家/地区,因此您必须预料到一个用户最终可能会出现在多个组中。

一种方法是引入辅助 class, UserCountry:

public record UserCountry(User user, Country country) {}

(如果您没有 Java 16+,这可能是 class)。

然后你可以将所有用户和他们的国家放在一起,然后按每个国家分组:

final Map<Country, List<User>> result =
    users.stream()
        .flatMap(user -> user.countries.stream().map(country -> new UserCountry(user, country)))
        .collect(
            Collectors.groupingBy(
                UserCountry::country,
                Collectors.mapping(UserCountry::user, Collectors.toList())));