Reputation: 131
There are two sets of objects, for example users - one from db(userSetDb) and another one - newly created objects (userSet). I need to compare these 2 sets, if userSetDb contains an element from userSet, set the fields (for example phone number) of users from userSetDb to phone numbers from userSet. (phone number field is not included into overridden equals method )
I cannot finish Stream API expression:
userSetDb.stream().filter(u -> userSet.contains(u))
.map(u -> userSet.stream().filter(u1 -> u1.equals(u))....
I know that I can remove similar users from userSetDb at first and then add all from userSet. But I wonder how I can do it using stream inside another stream. Is it a good practice to use stream in stream?
Upvotes: 3
Views: 97
Reputation: 1982
In order to do it with stream API, first of all you need to correlate equal users in both sets. Meaning you need to create pair of users from both sets that are considered equal:
userSetDb.stream()
.map(udb -> Pair.create(udb, userSet.stream().filter(u -> u.equals(udb)).findFirst()))
Here I am using org.apache.commons.math3.util.Pair
but any class that creates a tuple of objects would work.
After that filter only for pairs that have second element (for users that are present in both sets):
.filter(pair -> pair.getSecond().isPresent())
After that update fist element in pair with data from the second:
.forEach(pair -> pair.getFirst().setPhone(pair.getSecond().get().getPhone()));
And putting all together, you'll get something like:
userSetDb.stream()
.map(udb -> Pair.create(udb, userSet.stream().filter(u -> u.equals(udb)).findFirst()))
.filter(pair -> pair.getSecond().isPresent())
.forEach(pair -> pair.getFirst().setPhone(pair.getSecond().get().getPhone()));
Or as @Eklavya has mentioned in comments, instead of Pair
class from library you can use implementation of Map.Entry
:
userSetDb.stream()
.map(udb -> new AbstractMap.SimpleImmutableEntry<>(udb, userSet.stream().filter(u -> u.equals(udb)).findFirst()))
.filter(entry -> entry.getValue().isPresent())
.forEach(entry -> entry.getKey().setPhone(entry.getValue().get().getPhone()));
Upvotes: 3