Reputation: 31
Once again I was plainly scrolling thru w3schools Java basics when I saw this on the advanced sorting page:
public class Main {
public static void main(String[] args) {
// Create a list of cars
ArrayList<Car> myCars = new ArrayList<Car>();
myCars.add(new Car("BMW", "X5", 1999));
myCars.add(new Car("Honda", "Accord", 2006));
myCars.add(new Car("Ford", "Mustang", 1970));
// Sort the cars
Collections.sort(myCars);
Class Car's code:
class Car implements Comparable {
public String brand;
public String model;
public int year;
public Car(String b, String m, int y) {
brand = b;
model = m;
year = y;
}
// Decide how this object compares to other objects
public int compareTo(Object obj) {
Car other = (Car)obj;
if(year < other.year) return -1; // This object is smaller than the other one
if(year > other.year) return 1; // This object is larger than the other one
return 0; // Both objects are the same
So as we can see class Car implements Comparable, which compares one object to another. And in the main code when we added an array to store cars, we wrote here that the array stores the object of class car. And in Collections.sort() we only have one parameter - myCars, the array storing car objects.
We see a different behaviour for comparator:
public class Main {
public static void main(String[] args) {
ArrayList<Integer> myNumbers = new ArrayList<Integer>();
myNumbers.add(33);
myNumbers.add(15);
myNumbers.add(20);
myNumbers.add(34);
myNumbers.add(8);
myNumbers.add(12);
Comparator myComparator = new SortEvenFirst();
Collections.sort(myNumbers, myComparator);
for (int i : myNumbers) {
System.out.println(i);
the class SortEvenFirst():
class SortEvenFirst implements Comparator {
public int compare(Object obj1, Object obj2) {
// Make sure the objects are integers
Integer a = (Integer)obj1;
Integer b = (Integer)obj2;
// Check each number to see if it is even
// A number is even if the remainder when dividing by 2 is 0
boolean aIsEven = (a % 2) == 0;
boolean bIsEven = (b % 2) == 0;
if (aIsEven == bIsEven) {
// If both numbers are even or both are odd then use normal sorting rules
if (a < b) return -1;
if (a > b) return 1;
return 0;
} else {
// If a is even then it goes first, otherwise b goes first
if (aIsEven) {
return -1;
} else {
return 1;
}
}
}
}
So this has quite a different behavior for comparator: class SortEvenFirst() implements comparator BUT for the array it stores wrapper class Integer NOT the SortEvenFirst() Class. And we can see this further down the line in the main code we have to manually create a new variable for the SortEvenFirst() class and it is the additional parameter to Collections.sort()
From my understanding in the Comparable example it was somewhat convenient that they could include both information of the Cars object and also the method compareTo(). But I am still confused since I am still new to the concept of Comparable and Comparator (I dont even know the difference between the both of them)
So can someone explain if the code is written differently due to the circumstances itself or another reason, as well as how did the code automatically execute the method 'compareTo()' and 'compare()' without calling the function itself? I really need to know how these concepts work in this code and an in-depth explanation for a newbie would be helpful. Thanks!
Upvotes: -5
Views: 60
Reputation: 1122
Here you can read about Comparable
and Comparator
When should a class be Comparable and/or Comparator?
Regarding your question/example:
class SortEvenFirst() implements comparator BUT for the array it stores wrapper class Integer NOT the SortEvenFirst()
SortEvenFirst
is a class for comparing Integers
, not comparing SortEvenFirst
's instances
Comparable example it was somewhat convenient that they could include both information of the Cars object and also the method compareTo()
Sometimes you want to sort a list of object of the same type using different logic.
And then Comparator
helps, because you can have multiple implementations of Comparator
for a single class.
Using your example, in different places in your app you may need to sort cars by year, by brand + model alphabetically or by a new field (e.g. price)
public class Main {
public static void main(String[] args) {
ArrayList<Car> myCars = new ArrayList<>();
myCars.add(new Car("BMW","X5", 1999));
myCars.add(new Car("Honda", "Accord", 2006));
myCars.add(new Car("Ford", "Mustang", 1970));
System.out.println("Sorted by compareTo (actually by year)");
Collections.sort(myCars);
System.out.println(myCars);
System.out.println("Sorted by year");
Collections.sort(myCars, new CarYearComparator());
System.out.println(myCars);
System.out.println("Sorted by brand + model alphabetically");
Collections.sort(myCars, new CarBrandAndModelComparator());
System.out.println(myCars);
}
}
class Car implements Comparable<Car> {
public String brand;
public String model;
public int year;
public Car(String b, String m, int y) {
brand = b;
model = m;
year = y;
}
public int compareTo(Car other) {
if (year < other.year) return -1;
if (year > other.year) return 1;
return 0;
}
@Override
public String toString() {
return brand + " " + model + " " + year;
}
}
class CarYearComparator implements Comparator<Car> {
@Override
public int compare(Car c1, Car c2) {
return Integer.compare(c1.year, c2.year);
}
}
class CarBrandAndModelComparator implements Comparator<Car> {
@Override
public int compare(Car c1, Car c2) {
return (c1.brand + c1.model).compareTo(c2.brand + c2.model);
}
}
how did the code automatically execute the method 'compareTo()' and 'compare()' without calling the function itself?
If you do not pass Comparator
, then sort
expects to receive implementation of Comparable
and then sort
calls compareTo
.
If you pass Comparator
, then sort
calls compare
of the passed Comparator
.
Upvotes: 0