Update objects in one list based on values from second one using streams
I'd first create a mapping from TimeDiscount::getIdOfBook
to TimeDiscount
:
Map<Long, TimeDiscount> accumulator =
actualPromotions.stream()
.collect(toMap(TimeDiscount::getIdOfBook, Function.identity()));
Then I'd do:
booksToReturn.forEach(e -> {
TimeDiscount timeDiscount = accumulator.get(e.getIdOfBook());
if (timeDiscount != null) e.setDiscountRate(e.getDiscountRate() + timeDiscount.getDiscountRate());
});
or if you want to stay with the use of Optional
for some reason.
booksToReturn.forEach(e ->
Optional.ofNullable(accumulator.get(e.getIdOfBook()))
.ifPresent(p -> e.setDiscountRate(e.getDiscountRate() + p.getDiscountRate()))
);
This improves upon the inefficient lookup in actualPromotions.stream()
for each element of booksToReturn
.
Update one list based on another list using stream
Assuming that you want the currentList item to be replaced by the object from the updatedList the following should work:
currentList.stream().map((p) -> {
return updatedList.stream().filter(u -> p.equals(u)).findFirst().orElse(p);
}).collect(Collectors.toList());
Updating a List of Object from another list of object using java stream
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));
Update list of object from another list lambda expressions in java 8
I would use streams for that job.
Assuming your class MyObject
has getters and setters methods defined (getKey()
, getValue()
, setKey()
, setValue()
), you can do:
l1.forEach(myObject1 -> l2.stream()
.filter(myObject2 -> myObject1.getKey().equals(myObject2.getKey()))
.findAny().ifPresent(myObject2 -> myObject1.setValue(myObject2.getValue())));
If you can have duplicate keys then you should modify ifPresent()
to forEach()
:
l1.forEach(myObject1 -> l2.stream()
.filter(myObject2 -> myObject1.getKey().equals(myObject2.getKey()))
.forEach(myObject2 -> myObject1.setValue(myObject2.getValue())));
Update property of two objects in list based on matching objects in other list
If you care about performance, you could convert one of the lists to a lookup map with ID as a key and then update the other list. It would have a complexity of O(N).
You would create a lookup map like so:
Map<Integer, Object2> map = new HashMap<>();
for (Object2 obj : l2) {
map.put(obj.getId(), obj);
}
Or with Streams:
Map<Integer, Object2> map = l2.stream()
.collect(Collectors.toMap(Object2::getId, obj -> obj));
Now you can iterate over first list and update elements with value with help of the map.
l1.stream().forEach(o1 -> o1.setValue2(map.get(o1.getId()).getValue()));
Alternatively, if Object2
only has id
and value
, you could even create a map<id, value>
:
Map<Integer, String> map = new HashMap<>();
for (Object2 obj : list) {
map.put(obj.getId(), obj.getValue());
}
l1.stream().forEach(o1 -> o1.setValue2(map.get(o1.getId())));
populate a List<Object1> based on another List<Object2> using java 8 stream
Why use stream for this? Stream is not the right tool for mutating objects.
Use standard for
loops. Makes code easier to understand too.
List<Obligation> obligationList = ...;
List<ObligationStatus> statusList = ...;
// For better performance, make a map
Map<String, ObligationStatus> statusMap = new HashMap<>(statusList.size());
for (ObligationStatus status : statusList)
statusMap.put(status.getTopic(), status);
// Assign status values
for (Obligation obligation : obligationList) {
ObligationStatus status = statusMap.get(obligation.getTopic());
if (status != null) {
ob.setStatus(status.getStatus());
ob.setComment(status.getComment());
}
}
If you want to do some stream logic, the first part is a good candidate:
// For better performance, make a map
Map<String, ObligationStatus> statusMap = statusList.stream()
.collect(Collectors.toMap(ObligationStatus::getTopic, Function.identity()));
UPDATE
Noticed that question code did equalsIgnoreCase(...)
when comparing topic
values. If that is really needed, change the HashMap
to a case-insensitive TreeMap
:
Map<String, ObligationStatus> statusMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
The stream version of that gets convoluted, so better keep it old-style.
Related Topics
Redirecting to a Servlet from a Jsp on Button Click
Finding Repeated Words on a String and Counting the Repetitions
How to Call a Function from Other Activity Android
Find Difference Between Two Strings
Rounding to the Nearest Hundered-Thousandths
How to Split a String Between Letters and Digits (Or Between Digits and Letters)
Cannot Construct Instance of 'Java.Time.Localdate' - Spring Boot, Elasticseach, Jackson
How to Download a Pdf File in Chrome Using Selenium Webdriver
How to Mock a Rest Template Exchange
How to Check If an Excel Cell Is Empty Using Apache Poi
Get Unique Values from Arraylist in Java
Save Child Objects Automatically Using JPA Hibernate
Write to Text File from Multiple Threads
Printing a Statement Only Once in a While Loop
How to Create a Spring JPA Repository Findby Query Using a Property That Contains a Keyword
Eclipse Problems View Not Showing Errors Anymore
Calculate the Number of Items Displayed by Recyclerview and Place in a Textview