I read that :
whenever a collection need to be sorted, the elements must be mutually comparable.
I wrote the below code and it worked correctly. Can you please tell how class b and class c are mutually comparable and what is the meaning of being "mutually comparable"?
import java.util.ArrayList;
import java.util.Collections;
class b implements Comparable<c> {
String str1;
b(String str1) {
this.str1 = str1;
}
public int compareTo(c object) {
return str1.compareTo(object.str1);
}
}
class c implements Comparable<b> {
String str1;
c(String str1) {
this.str1 = str1;
}
public int compareTo(b object) {
return str1.compareTo(object.str1);
}
}
public class a {
public static void main(String[] args) {
b obj1 = new b("monster");
c obj2 = new c("aman");
ArrayList list = new ArrayList();
list.add(obj1);
list.add(obj2);
System.out.println("unsorted list = "+list);
Collections.sort(list);
System.out.println("sorted list = "+list);
}
}
Mutually comparable means that instances of both classes must be comparable to the other.
In case of type
A
and typeB
:A
must implementComparable<T>
whereT
extendsB
(or isB
)B
must implementComparable<U>
whereU
extendsA
(or isA
)a>b
then it must be sob<a
. And ifa<b
then it must be sob>a
. And ifa==b
then it must be sob==a
.So that the following code can be written:
If type
A
and typeB
are the same, thena
andb
are obviously mutually comparable.Sorting algorithms usually require the elements to be mutually comparable so they can compare any 2 of the sortable elements to each other.
Back to your question
Your case is special. Your 2 objects
obj1
andobj2
are mutually comparable according to the definition. Yourobj1
andobj2
instances are mutually comparable, but yourb
andc
classes are not.However, if you would pass another instance of either type
a
or typeb
, all elements would be not. Because if we would select 2 instances from the collection of the same type, they would not implementComparable
to the same type.Your code works only by chance and it has so many mistakes that they cancel out each other resulting into working code.
ArrayList list = new ArrayList();
What is a raw type and why shouldn't we use it?Comparable<T>
,T
should be a super type of that class. For exampleInteger implements Comparable<Number>
would be just as fine.That means that each element from that collection must be comparable to each other and in your case that works only because you added only 2 elements (adding more would result into ClassCastException at runtime).
If you want a sortable collection containing both
B
andC
, find common parent of those classes (or perhaps create an interface for it, lets call itBC
) then you would go:and changle your list declaration and creation to:
ArrayList<BC> list = new ArrayList<>();
EDIT:
To truly guarantee that
ArrayList<BC>
is sortable, we need to change theBC
's declaration to:Otherwise we could have
class D implements BC
but notComparable<BC>
. With this new annotation we say "anything that implementsBC
must implementComparable<BC>
as well".Now you can write only
(Also note that you can add
getString()
method to interfaceBC
to avoid theinstanceof
testing and casting in the compare method)In order for classes
A
andB
to be mutually comparable, these requirements need to be satisfied:compareTo
on an instance ofA
passing an instance ofB
must be allowedcompareTo
on an instance ofB
passing an instance ofA
must be alloweda.compareTo(b)
returnsx
, thenb.compareTo(a)
must return a valuey
with the opposite sign, or zero, whenx
is zero.The classes in your code are not mutually comparable, because an attempt to pass an instance of
c
tob
'scompareTo
(and vice versa) works fine. However, they are not comparable to instances of their own classes, which would create a problem if you were to add more items to the collection to be sorted.In order for the container to be sortable, your class needs to be comparable to instances of its own type as well.
It means that for any two items in the collection, you must be able to compare A to B and vice versa.