How to use Comparator in Java to sort

Dan picture Dan · May 15, 2010 · Viewed 540.4k times · Source

I learned how to use the comparable but I'm having difficulty with the Comparator. I am having a error in my code:

Exception in thread "main" java.lang.ClassCastException: New.People cannot be cast to java.lang.Comparable
 at java.util.Arrays.mergeSort(Unknown Source)
 at java.util.Arrays.sort(Unknown Source)
 at java.util.Collections.sort(Unknown Source)
 at New.TestPeople.main(TestPeople.java:18)

Here is my code:

import java.util.Comparator;

public class People implements Comparator {
   private int id;
   private String info;
   private double price;

   public People(int newid, String newinfo, double newprice) {
       setid(newid);
       setinfo(newinfo);
       setprice(newprice);
   }

   public int getid() {
       return id;
   }

   public void setid(int id) {
       this.id = id;
   }

   public String getinfo() {
       return info;
   }

   public void setinfo(String info) {
       this.info = info;
   }

   public double getprice() {
       return price;
   }

   public void setprice(double price) {
       this.price = price;
   }

   public int compare(Object obj1, Object obj2) {
       Integer p1 = ((People) obj1).getid();
       Integer p2 = ((People) obj2).getid();

       if (p1 > p2) {
           return 1;
       } else if (p1 < p2){
           return -1;
       } else {
           return 0;
       }
    }
}
import java.util.ArrayList;
import java.util.Collections;

public class TestPeople {
    public static void main(String[] args) {
        ArrayList peps = new ArrayList();

        peps.add(new People(123, "M", 14.25));
        peps.add(new People(234, "M", 6.21));
        peps.add(new People(362, "F", 9.23));
        peps.add(new People(111, "M", 65.99));
        peps.add(new People(535, "F", 9.23));

        Collections.sort(peps);

        for (int i = 0; i < peps.size(); i++){
            System.out.println(peps.get(i));
        }
    }
}

I believe it has to do something with the casting in the compare method but I was playing around with it and still could not find the solution

Answer

Bart Kiers picture Bart Kiers · May 15, 2010

There are a couple of awkward things with your example class:

  • it's called People while it has a price and info (more something for objects, not people);
  • when naming a class as a plural of something, it suggests it is an abstraction of more than one thing.

Anyway, here's a demo of how to use a Comparator<T>:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, new LexicographicComparator());
        System.out.println(people);
        Collections.sort(people, new AgeComparator());
        System.out.println(people);
    }
}

class LexicographicComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.name.compareToIgnoreCase(b.name);
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }
}

class Person {

    String name;
    int age;

    Person(String n, int a) {
        name = n;
        age = a;
    }

    @Override
    public String toString() {
        return String.format("{name=%s, age=%d}", name, age);
    }
}

EDIT

And an equivalent Java 8 demo would look like this:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, (a, b) -> a.name.compareToIgnoreCase(b.name));
        System.out.println(people);
        Collections.sort(people, (a, b) -> a.age < b.age ? -1 : a.age == b.age ? 0 : 1);
        System.out.println(people);
    }
}