0

I have class like:

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;
}

And I need to sort users by country's name. I made something like this:

        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;
    }

But I want to avoid adding elements to map in foreach. I prefer something like Collectors.toMap() or groupingBy but I don't have any idea how can I do this in this place.

Mateusz
  • 323
  • 2
  • 11
  • 23

1 Answers1

1

If I understood your question correctly, you want to group the users by their countries. As a user can have many countries, you have to expect a user to possibly end up in multiple groups.

One way would be to introduce an auxiliary class, UserCountry:

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

(this could be a class if you do not have Java 16+).

Then you could flatMap all users together with their countries, and group by each country:

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())));
Andreas Berheim Brudin
  • 2,214
  • 1
  • 18
  • 13