Search code examples
javasortingdictionarysortedmap

SortedMap with Comparator ClassCast Exception


Why am getting a ClassCastException at (Person p2 = (Person) o2;) in overridden compare method . :(

Actually Instead of Person Object the values in compare overridden method is coming as "Jim" and "Jack" (Key values). So the Cast Cast Exception . But Why is it coming with keys not values i,e the Person object , Why is it only applied for keys . Are there any other way to sort it based on values .

Please correct me if am wrong

1) We can Pass the comparator object in the TreeMap which will sort it accordingly.?

2) Always the Sorting is performed over Keys . ?

3) How can we sort a Map over its values without using anymore collection object (Is it possible) and why is not supported by default ?

public class HashTableExamples {

/**
 * @param args
 */
public static void main(String[] args) {

    SortedMap persorSorted = new TreeMap(new Comparator() {

        @Override 
        public int compare(Object o1, Object o2) {
            Person p2 = (Person) o2;
            return 2;
        }
    });

    Person p = new Person(10);
    Person p1 = new Person(20);
    persorSorted.put("Jim", p);
    persorSorted.put("Jack", p1);
    Iterator sortedit = persorSorted.entrySet().iterator();
    while (sortedit.hasNext()) {
        Map.Entry pairs = (Map.Entry) sortedit.next();
        Person pw = (Person) pairs.getValue();
        System.out.println("From SortedMap : " + pw.getAge());
    }
}

public static class Person {
    Person(int agevalue) {
        this.age = agevalue;
    }

    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Solution

  • Yes, TreeMap always sorts on keys.

    As to why it's not "supported by default" -- it's because there doesn't exist a data structure in general that supports it efficiently. It's not supported efficiently in any programming language, because the point of a Map is to be able to look things up by their key, and sorting by values means you can't organize the data in a way that makes it efficient to look things up by keys.

    If you must sort a Map's entries by value, you can use something like this:

    List<Map.Entry<Foo, Bar>> entryList = 
      new ArrayList<Map.Entry<Foo, Bar>>(map.entrySet());
    Collections.sort(entryList, new Comparator<Map.Entry<Foo, Bar>>() {
      public int compare(Map.Entry<Foo, Bar> entry1, Map.Entry<Foo, Bar> entry2) {
        return entry1.getValue().compareTo(entry2.getValue());
      }
    });
    

    Alternately, if you like, you can use an alternate comparator to compare the values if you don't control the implementation of the value type.