'How to Collect elements of the Stream with incosistent data into a Map?
I have a method that receives a List of emails and ids as Strings.
I am making an API call then which has a limit of 100 email searches per call:
userService.listUsersByEmails(List<String> emails)
It returns a list of User objects.
Currently, I am collecting the results into a single List of User objects.
List<User> users= Lists.partition(emails, 100)//
.stream()
.map(userService:: listUsersByEmails)// this method makes API calls which takes 100
.flatMap(List::stream) // emails as params (comma separated) & returns
.collect(Collectors.toList()); // User objects for each email found
The listUserByEmails method returns User object for each email found in the DB.
But a few results might not have the emailAddress attribute, but they are guaranteed to have an Id, firstName and LastName.
I am hoping to create a map of type Map<String, User>s like that
Key (emailAddress) - "[email protected]" , Value - John Doe's User object.
The User objects that gets returned looks like this
{id: 123456789
emailAddress: [email protected]
firstName: John
lastName: Doe
displayName: Sharon
title: null
company: DEVELOP
username: s-dev
location: null
accountType: NORMAL}
Is there any option to handle all Users (with email and without) together in one go?
Solution 1:[1]
This approach will allow to handle all User objects in the stream regardless of whether they have an email.
Collectors.partitioningBy splits the data into two parts based on the given predicate (whether email is present or not), and returns map with a key of type Boolean.
Then, based on this map, the two district maps userByEmail and userById are being populated.
That's how both maps could be encapsulated in a class and accessed via an instance of this class:
public class UserStorage {
private Map<String, User> userByEmail = new HashMap<>();
private Map<Long, User> userById = new HashMap<>();
public void addUsers(List<User> source) {
Map<Boolean, User> userByHasEmail = source
.stream()
.map(userService:: listUsersByEmails)
.flatMap(List::stream)
.collect(Collectors.partitioningBy(
user -> user.getEmailAddress() != null && !user.getEmailAddress().isBlank(),
Function.identity()));
for (Map.Entry<Boolean, User> entry: userByHasEmail.entrySet()) {
if (entry.getKey()) {
userByEmail.put(entry.getValue().getEmailAddress(), entry.getValue());
} else {
userById.put(entry.getValue().getId(), entry.getValue());
}
}
}
public User getUser(String email) {
return userByEmail.get(email);
}
public User getUser(Long id) {
return userById.get(id);
}
public User getUser(String email, Long id) {
return userByEmail.getOrDefault(email, userById.get(id));
}
}
public static void main(String[] args) {
UserStorage storage = new UserStorage();
storage.addUsers(Lists.partition(emails, 100));
User userWithEmail = storage.getUser("[email protected]");
User userWithNoEmail = storage.getUser(123456789L);
User user = storage.getUser("anyString", 123456789L);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
