Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating a subsection of a list with an "id" field

I am trying to learn how to use the lambda functions for sleeker code but struggling to make this work.

I have two lists. The "old" list is always shorter or the same length as the "updated list". I want to take the objects from the "updated list" and overwrite the "stale objects" in the shorter "old list". The lists have a unique field for each object.

For example, it is a bit like updating books in a library with new editions. The UUID (title+author) remains the same but the new object replaces the old on the shelf with a new book/object.

I know I could do it the "long way" and make a HashMap<MyUniqueFieldInMyObject, MyObject> and then take the new List<MyUpdatedObjects> and do the same.

I.e. Have HashMap<UniqueField, MyOldObject> and HashMap<UniqueField, MyUpdatedObject>, then iterate over the old objects with a pseudo "if updated objects have an entry with the same key, overwrite the value with the updated value"...

But...

Is there a "nicer" shorted way to do this with functional lambda statements?

I was thinking along the lines of:

List<MyObject> updatedList;
List<MyObject> oldList;

updatedList.forEach(MyObject -> {

    String id = MyObject.getId();

    if (oldList.stream().anyMatcher(MyObject -> 
        MyObject.getId().matches(id)) {
           //Do the replacement here? If so...how?
       }
}

Which is where I am lost!

Thanks for any guidance.

like image 243
Jcov Avatar asked Aug 18 '18 15:08

Jcov


People also ask

How do you update a column based on a filter of another column?

UPDATE table SET col = new_value WHERE col = old_value AND other_col = some_other_value; UPDATE table SET col = new_value WHERE col = old_value OR other_col = some_other_value; As you can see, you can expand the WHERE clause as much as you'd like in order to filter down the rows for updating to what you need.


1 Answers

If you want to update the list in place rather than making a new list, you can use List.replaceAll:

oldList.replaceAll(old -> 
    updateListe.stream()
        .filter(updated -> updated.getId().equals(old.getId())
        .findFirst()
        .orElse(old)
);

The main problem with this solution is that its complexity is O(size-of-old*size-of-updated). The approach you described as "long way" can protect you from having to iterate over the entire updated list for every entry in the old list:

// note that this will throw if there are multiple entries with the same id
Map<String, MyObject> updatedMap = updatedList.stream()
                                         .collect(toMap(MyObject::getId, x->x));

oldList.replaceAll(old -> updatedMap.getOrDefault(old.getId(), old));
like image 188
Misha Avatar answered Sep 22 '22 02:09

Misha