Reputation: 55
I have a list of Object A
A{
name
age
dob
}
and list of Object B
B{
name
dob
}
.
I always get the List of A with A.dob as null. and List of B with B.dob having value. I need to loop thru List of A and List of B find the common objects using the name field in each A and B object and update A.dob using B.dob
Can this be done using streams?
Upvotes: 3
Views: 5069
Reputation: 5739
You should not use Stream APIs to change the state of an Object.
If you still want to modify it then,
You can iterate each element from the list of A
, filter if dob is null, find dob against the respective name in the list of B
.
List<A> aList = new ArrayList<>();
List<B> bList = new ArrayList<>();
aList.stream()
.filter( a -> a.dob == null)
.forEach( a -> {
Predicate<B> nameFilter = b -> b.name.equals(a.name);
a.dob = findDob(nameFilter, bList);
});
static String findDob(Predicate<B> nameFilter, List<B> bList) {
B b = bList.stream()
.filter(nameFilter)
.findFirst()
.orElse(new B());
return b.dob;
}
Alternate efficient solution: Considering you have a unique name for each object B, you can prepare lookup and find age using that map, this way you do not need to iterate bList
for every iteration of aList
List<A> aList = new ArrayList<>();
List<B> bList = new ArrayList<>();
Map<String, String> nameDobLookup = bList.stream()
.collect(Collectors.toMap(b -> b.name, b -> b.dob));
aList.stream()
.filter(a -> a.dob == null)
.forEach(a -> a.dob = nameDobLookup.get(a.name));
Upvotes: 3
Reputation: 1043
I'd suggest modifying the list of A objects in a forEach loop:
// define: List<A> aList =
// define: List<B> bList =
aList.forEach(aListElement -> {
// find the first B object with matching name:
Optional<B> matchingBElem = bList.stream()
.filter(bElem -> Objects.equals(aListElement.getName(), bElem.getName()))
.findFirst();
// and use it to set the dob value in this A list element:
if (matchingBElem.isPresent()) {
aListElement.setDob(matchingBElem.get().getDob());
}
}
);
Upvotes: 1