In relation to this question, which is discussing the possibilities to monitor the process of Collections.sort()
, I would like to know if there is a good way to cancel a call to Collections.sort()
using a ProgressMonitor
.
One approach to monitor progress is to use a custom Comparator that keeps track of its invocations.
Along this line, would it make sense to let this Comparator check for a cancelled
flag and return immediately 0
, without doing any actual comparison? This would save the time that is needed to do the acutal comparison, but it would not stop the iteration on the list elements.
public class ProgressMonitoringComparator<T extends Comparable<T>> implements Comparator<T> {
private volatile long invocationCount = 0;
private volatile boolean cancelled = false;
private final long elementCount;
private final ProgressMonitor monitor;
public ProgressMonitoringComparator(long elementCount) {
this.elementCount = elementCount;
this.monitor = null;
}
public ProgressMonitoringComparator(ProgressMonitor monitor) {
this.monitor = monitor;
this.elementCount = -1;
}
public ProgressMonitoringComparator() {
this(0);
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public float getProgress() {
if(elementCount <= 0) {
return -1;
}
long totalInvocationsNeeded = (long)(elementCount * Math.log(elementCount));
return totalInvocationsNeeded / invocationCount;
}
@Override
public int compare(T o1, T o2) {
if(cancelled || (monitor != null && monitor.isCancelled())) {
return 0;
}
invocationCount++;
if(monitor != null) {
monitor.worked();
}
return o1.compareTo(o2);
}
}
A second approach, as suggested by user2717954, could be the following:
public class CancellableComparator<T extends Comparable<T>> implements Comparator<T> {
private volatile boolean cancelled = false;
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public int compare(T o1, T o2) {
if(cancelled) {
throw new CancelException();
}
return o1.compareTo(o2);
}
}