0

I have an entity UserId that has both a name and an email. I need to return a map where the UserId can be mapped to either the name or email. Currently this is how it looks where we are able to obtain only the email.

 Map<UserId, String> userIdToEmailMap = futureList.stream()
                     .map(CompletableFuture::join)
                     .filter(Optional::isPresent)
                     .map(userProfile -> userProfile.get())
                     .collect(Collectors.toMap(UserProfile::getUserId, UserProfile::getEmail));

And I need even the name to be retrieved. Is there a way I can do that without having to create another separate map and having to return a list of Maps?

This is wrong but something like this -

Map<UserId, String> userIdToEmailMap = futureList.stream()
                     .map(CompletableFuture::join)
                     .filter(Optional::isPresent)
                     .map(userProfile -> userProfile.get())
                     .collect(Collectors.toMap(UserProfile::getUserId, UserProfile::getEmail, UserProfile::getName));
4
  • 1
    Keys in a map are supposed to be unique. Commented Dec 2, 2022 at 21:36
  • So would I need to use some other data structure to handle this case? Commented Dec 2, 2022 at 21:38
  • 2
    Sounds like an XY Problem to me. What are you actually trying to achieve? What is the goal here? Commented Dec 2, 2022 at 21:41
  • 1
    If you want to retrieve name or email by ID, why not store the UserProfile itself: Collectors.toMap(UserProfile::getUserId, u -> u) Commented Dec 2, 2022 at 21:53

1 Answer 1

2

If you want to map both a name and an email to a particular Key, then you need a type that would hold references to both name and an email.

So you might consider creating a map of type Map<UserId, UserProfile> associating UserProfile with its UserId. Name and email would be accessible through get().getEmail() and get().getName() respectively.

Map<UserId, UserProfile> userIdToEmailMap = futureList.stream()
    .map(CompletableFuture::join)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toMap(
        UserProfile::getUserId,
        Function.identity()
    ));
Sign up to request clarification or add additional context in comments.

4 Comments

How would the output of this Map look like?
@user3927038 Not sure what do you exactly mean by saying "output". If you're asking how it would look like if you print it on the console then it's better to try it out and see for yourself, don't forget that method toString() should be overridden in both UserId and UserProfile classes. Note that if you need a nicely formatted well-readable string which should be printed, or stored into a file, then you've probably had taken the wrong route, Map is not a mean of string-formatting.
What I mean is when I'm writing a test case, for example previously with only the userID and email my test case was doing this - //active users setup Map<UserId, String> activeUserProfileMap = new HashMap<>() { { put(USERID_MEMBER_1, USERID_MEMBER_1_EMAIL); } }; when(pService.getEmailsAndNameOfUsers(List.of(USERID_MEMBER_1, USERID_MEMBER_2))).thenReturn(activeUserProfileMap); But now since I have the complete UserProfile instead of string, I'm wondering how the map would look like to re-write this test
@user3927038 Firstly, you should clarify: you need the Map containing names and emails for busyness logic of your service? The Map in the test should have identical type, you can't stub the behavior of the service with a Map which type doesn't match.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.