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 ofequals()
. - It would be much cleaner if
startTime
would be of typeLocalDateTime
and not aString
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 usingretainAll()
. It will turn the worst case quadratic time instead into a linear. - Method name
removeduplicates()
and parameter namere
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());
}