Collections Sort(List<T>,Comparator<? Super T>) Method Example

Collections sort(ListT,Comparator? super T) method example

Building upon your existing Student class, this is how I usually do it, especially if I need more than one comparator.

public class Student implements Comparable<Student> {

String name;
int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return name + ":" + age;
}

@Override
public int compareTo(Student o) {
return Comparators.NAME.compare(this, o);
}

public static class Comparators {

public static Comparator<Student> NAME = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
};
public static Comparator<Student> AGE = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
};
public static Comparator<Student> NAMEANDAGE = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int i = o1.name.compareTo(o2.name);
if (i == 0) {
i = o1.age - o2.age;
}
return i;
}
};
}
}

Usage:

List<Student> studentList = new LinkedList<>();
Collections.sort(studentList, Student.Comparators.AGE);

EDIT

Since the release of Java 8 the inner class Comparators may be greatly simplified using lambdas. Java 8 also introduces a new method for the Comparator object thenComparing, which removes the need for doing manual checking of each comparator when nesting them. Below is the Java 8 implementation of the Student.Comparators class with these changes taken into account.

public static class Comparators {
public static final Comparator<Student> NAME = (Student o1, Student o2) -> o1.name.compareTo(o2.name);
public static final Comparator<Student> AGE = (Student o1, Student o2) -> Integer.compare(o1.age, o2.age);
public static final Comparator<Student> NAMEANDAGE = (Student o1, Student o2) -> NAME.thenComparing(AGE).compare(o1, o2);
}

Confusion about Collections.sort(ListT list, Comparator? super T c) example

for d1.age - d2.age

  • if negative number, then d1 is logically less than d2 in sort order
  • if positive, then d1 is logically greather than d2 in sort order
  • if 0, then objects are equal

You can refer the javadoc for compare method

So when you are sorting dogs, and your compare method is comparing their ages, hence Tammy is less than Lacy according to the your method implementation.

Making Dog implement both Comparable and Comparator seems like a bad idea to me.

  • Collections.sort(list) will cause compareTo() method to be
    invoked
  • Collections.sort(list, new Dog()) will cause compare() method to be invoked

I believe you should look into sorting user defined object using Comparable and Comparator

Error Message: The method sort(ListT) in the type Collections is not applicable for the arguments (ArrayListDate)

Because Collections.sort expects java.lang.Comparable and not your Comparable interface, change your Date class to implement the java.lang.Comparable.

public class Date implements java.lang.Comparable<Date>{
..
}

If you still want to define your own Comparable for some reasons and you still want to use Collections.sort then the your Comparable has to be java.util.Comparable

interface Comparable<T> extends java.lang.Comparable<T> {

}

Collections.sort() declaration: why ? super T rather than T

Your proposed signature would probably work in Java-8. However in previous Java versions type inference was not so smart. Consider that you have List<java.sql.Date>. Note that java.sql.Date extends java.util.Date which implements Comparable<java.util.Date>. When you compile

List<java.sql.Date> list = new ArrayList<>();
Collections.sort(list);

It perfectly works in Java-7. Here T is inferred to be java.sql.Date which is actually Comparable<java.util.Date> which is Comparable<? super java.sql.Date>. However let's try your signature:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {}

List<java.sql.Date> list = new ArrayList<>();
sort(list);

Here T should be inferred as java.util.Date. However Java 7 specification does not allow such inference. Hence this code can be compiled with Java-8, but fails when compiled under Java-7:

Main.java:14: error: method sort in class Main cannot be applied to given types;
sort(list);
^
required: List<? extends T>
found: List<Date>
reason: inferred type does not conform to declared bound(s)
inferred: Date
bound(s): Comparable<Date>
where T is a type-variable:
T extends Comparable<T> declared in method <T>sort(List<? extends T>)
1 error

Type inference was greatly improved in Java-8. Separate JLS chapter 18 is dedicated to it now, while in Java-7 the rules were much simpler.

Trying to solve The method sort(ListT, Comparator? super T) in the type Collections is not applicable for the arguments

The problem is that the list you're sorting has been declared as a list that can contain arbitrary objects. You can't apply a comparator of Patients to objects that might not be Patients.

To solve it, declare your list as a list of Patients:

List<Patient> list = new ArrayList<>(waitingList)

Error on Java Collection.sort

You're trying to sort a List<String> with a Comparator<Students>, which evidently cannot work. Perhaps you meant to use a List<Students> instead? Or a Comparator<String>?

Also, you have this:

@Override
public int compareTo(Students student) {
return this.compareTo(student);
}

which will simply call itself indefinitely. I'm not fully sure what you wanted to do there; perhaps sort by the last name as you do in StudentComparator?

@Override
public int compareTo(Students student) {
return getLastname().compareTo(student.getLastname());
}

Unckecked method invocation warning on Collections.sort()

@Aominè had it right : MyType implemented Comparable instead of Comparable<MyType>. The warning is gone now that I've changed this.



Related Topics



Leave a reply



Submit