I have two classes - Task (which implements Comparable) and DeadlinedTask (where DeadlinedTask extends Task). And for each of them I have written an overloaded compareTo function (each has compareTo(Task) and compareTo(DeadlinedTask)).
The idea is that I can sort normal Tasks by category, and DeadlinedTasks by deadline, but I also want all of the DeadlinedTasks to be sorted above the Tasks.
When I call Collections.sort(myListOfTasks) on a list of only Tasks (no DeadlinedTasks), everything works like a charm. However when I have a list of both Tasks and DeadlinedTasks, the objects change order, but they are not fully sorted.
I have tried returning numbers other than 1 on the interclass compares (1, 1000, 1000000 all did the same thing). Is there any way to do this through compareTo and Collections.sort, is there a different java functionality I can use, or do I have to write my own search function (as a Comparator?)?
Task compareTo Methods:
public int compareTo(Task other){
if(this.GetCategory().compareTo(other.GetCategory())==0)
return this.GetName().compareTo(other.GetName());
else
return this.GetCategory().compareTo(other.GetCategory());
}
public int compareTo(DeadlinedTask other){
return 1;
}
DeadlinedTask compareTo Methods:
public int compareTo(Task other){
return -1;
}
public int compareTo(DeadlinedTask other){
if(this.GetDeadline().compareTo(other.GetDeadline())==0)
return this.GetName().compareTo(other.GetName());
else
return this.GetDeadline().compareTo(other.GetDeadline());
}
Thanks for any help
... or do I have to write my own search function (as a Comparator?)?
Yes. I think that's the best way.
The normal way to handle equals
and compareTo
is to return false
(for equals
) or throw ClassCastException
(for compareTo
) if the arguments actual type doesn't match the actual type of this
.
If you try to implement equals
or compareTo
for subtypes, you can easily create semantic anomalies such as:
a.equals(b)
and b.equals(a)
returning different values, ora.compareTo(b)
and b.compareTo(a)
returning inconsistent values.Avoiding those anomalies would entail making the supertype aware of the subtype. That is a bad from a design perspective because it restricts your ability to create more subtypes in the future.
For use-cases where you need to implement a rule that orders instances of two or more different classes, a Comparator
is the best solution.
Per class, only one compareTo method can be used to implement the Comparable interface. If you use Comparable without generics, then this is
public int compareTo(Object o)
If you're using generics, e.g. Comparable<Task>
, then it's
public int compareTo(Task o)
Your compareTo(DeadlinedTask o)
method will be ignored concerning the Comparable<Task>
interface. It just "accidentally" has the same name, but it's an independent overloading.
(By the way, it's not possible to implement both Comparable<Task>
and Comparable<DeadlineTask>
).
So what you'll have to do instead, is change your Task.compareTo(Task o)
method to use instanceof
(it has to use runtime information after all). I agree with Stephen, that it would even be better to write a Comparator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With