Replace or update an object in a list knowing only its UUID

Viewed 460

I know similar questions have been asked already, but every time the answers revolve around "use a Map instead".

In my case, I HAVE to use a List. More precisely, I can use other data structures for treatment, but the information will be stored ultimately in the form of a List.

Here is the situation : I have an object, which I will call Sequence, containing a List of objects I will call Phase.

Among other properties, the Phase object is given a UUID through ObjectId

During a given treatment, I have to replace an existing Phase inside the List<Phase> contained in Sequence by another Phase. The input for this are the replacement Phase object and a String value of the ObjectId of the Phase to replace

I was hoping to be able to do something like this using Java8 :

public void replacePhase(Sequence sequence, Phase replacementPhase, String idPhaseToBeReplaced) {
         List<Phase> phaseList = sequence.getPhaseslist();
         Phase phaseToBeReplaced = phaseList.stream().filter(p -> p.getId().toString().equalsIgnoreCase(idPhaseToBeReplaced)).findFirst().orElse(null);
         if (phaseToBeReplaced != null) {
             phaseToBeReplaced = replacementPhase;
         }

And voilĂ , the List<Phase> would be updated.

I know something like this will work :

    public void replacePhase(Sequence sequence, Phase replacementPhase, String idPhaseToBeReplaced) {
             List<Phase> phaseList = sequence.getPhaseslist();
             Phase phaseToBeReplaced = phaseList.stream().filter(p -> p.getId().toString().equalsIgnoreCase(idPhaseToBeReplaced)).findFirst().orElse(null);
             if (phaseToBeReplaced != null) {
                 int i = phaseList.indexOf(phaseToBeReplaced );
                 phaseList.set(i, replacementPhase);
                 phaseToBeReplaced = replacementPhase;
             }

But it doesn't seem more efficient that using a for loop on phaseList with a break when finding a Phase with the desired UUID.

So my question is : is there a way, using List data structure, to find an object based on a (in this case, unique) property and then replace said object inside the List by another (of the same type), preserving order? Preferably without iterating over the whole List and using Java8 functionnalities?

3 Answers

You seem to be looking for List#replaceAll such as :

sequence.getPhasesList()
        .replaceAll(phase -> phase.getId().toString()
                .equalsIgnoreCase(idPhaseToBeReplaced) ? replacementPhase : phase);

In order to make your replace functionality work in short-circuit fashion, use ListIterator:

ListIterator<Phase> iterator = phaseList.listIterator();
while(iterator.hasNext()){
    Phase phase = iterator.next();
    if(phase.getId().toString().equalsIgnoreCase(idPhaseToBeReplaced)){ 
        iterator.set(replacementPhase);
        break;
    }
}

In case the id is not unique, just remove the break. Or use List::replaceAll.

If you keep the list sorted you can find the item using binary search, that would be faster than iterating the list.

    Collections.binarySearch

If you need to keep it sorted by insertion order, use a LinkedHashMap

Related