Home > Blockchain >  Remove objects having same ID and its Status
Remove objects having same ID and its Status

Time:06-16

I have a array list results which is having bellow objects.

Results[Event[ID=ace-453, status=Inprogress , startTime= "2020-04-20 07:05:28"], 
        Event[ID=ace-453, status=Inprogress , startTime= "2020-04-20 07:07:28"],
        Event[ID=ace-453, status=Inprogress , startTime= "2020-04-20 09:07:28"],
        Event[ID=ace-453, status=Inprogress , startTime= "2020-04-20 07:07:34"] 
        
       ]

I am trying to fetch a single record which is having maximum start time and remove the other object from the list. The following list is updated on runtime so I want to compare the object and only get the object with maximum time at last.

I tried

public List<Event> removeduplicates(List<Event> re){
List<Event> results = new Arraylist<Events>();
results = re;
for(Event e : re){
   if(e.getId() != null && !e.getid().isEmpty() && e.getStatus() == "InProgress"){
     for(Event e1 : results){
        if(e.getId().euqals(e1.getId()) && (e.getStatus().equals(e1.getStatus()))){
           DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-mm-dd HH:mm:ss");
           LocalDateTime dt1 = LocalDateTime.parse(e.getStarttime(),formatter);
           LocalDateTime dt2 = LocalDateTime.parse(e1.getStarttime(),formatter);
          if(dt1.isBefore(dt2)){
            result.remove(e);
           }

      }
   }

 }

}

but I am getting null list at the end. also i am not able to use .remove() here.

CodePudding user response:

If I understood you correctly, your goal is to remove duplicated events having the same id and status and retain only one of them having the latest time.

The issues with your code:

  • You're using identity comparison for strings strings e.getStatus() == "InProgress" instead of equals().
  • It would be much cleaner if startTime would be of type LocalDateTime and not a String in the first place.
  • It's not clear do you want to modify the existing list or generate a new one as result of the method execution (because in the code you are creating a new list and then immediately reassigning the variable). In case if you need to modify the existing list, it would more performant not to remove elements one by one, but instead generate a HashSet of events that should be retained and then remove all other events in one go using retainAll(). It will turn the worst case quadratic time instead into a linear.
  • Method name removeduplicates() and parameter name re are not aligned with Java naming conventions.

Assuming that equality of events according to the equals/hashCode implementation isn't based solely on id and status. We can generate a map with keys created by concatenating id and status. And then generate a resulting list from based on the values of this map.

The code below generates a new list, if you need to modify the one that was passed to a method, then replace Collectors.toList() with Collectors.toSet() and apply retainAll() on the initial list of events.

public List<Event> removeDuplicates(List<Event> events) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-mm-dd HH:mm:ss");
    
    return events.stream()
        .filter(e -> e.getId() != null && !e.getId().isEmpty() && e.getStatus().equals("InProgress"))
        .collect(Collectors.groupingBy(
            e -> e.getId()   ":"   e.getStatus(),
            Collectors.maxBy(Comparator.comparing(e -> LocalDateTime.parse(e.getStartTime(), formatter)))
        ))
        .values().stream()
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());
}

CodePudding user response:

This might be a good case where using streams might be very handy instead of a classic for-loop, because the method names will make it obvious what is going on in the method, i.e. grouping by id status and and maping to the object having the max starttime. Example: assuming a class Event which looks something like :

class Event {
    String id;
    String status;
    String startTime;
}

And a sample input list:

List<Event> result = List.of(
        new Event("ace-453", "Inprogress",  "2020-04-20 07:05:28"),
        new Event("ace-453", "Inprogress",  "2020-04-20 07:07:28"),
        new Event("ace-453", "Inprogress",  "2020-04-20 09:07:28"),
        new Event("ace-453", "Inprogress",  "2020-04-20 07:07:34")
);

then your method could look like

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;


....


public List<Event> removeduplicates(List<Event> result){
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    return new ArrayList<>(
            result.stream()
                    .collect(Collectors.toMap(
                            event -> event.getId()   event.getStatus(),
                            Function.identity(),
                            BinaryOperator.maxBy(
                                    Comparator.comparing(event -> LocalDateTime.parse(event.getStartTime(),formatter)))))
                    .values());
}
  • Related