Hero
Hero

Reputation: 647

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;
    }
}

Upvotes: 3

Views: 225

Answers (2)

Louis Wasserman
Louis Wasserman

Reputation: 198371

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.

Upvotes: 1

Daniel Kaplan
Daniel Kaplan

Reputation: 67474

If you look at the documentation for TreeMap you'll see it says:

Constructs a new, empty tree map, ordered according to the given comparator. All keys inserted into the map must be mutually comparable by the given comparator: comparator.compare(k1, k2) must not throw a ClassCastException for any keys k1 and k2 in the map. If the user attempts to put a key into the map that violates this constraint, the put(Object key, Object value) call will throw a ClassCastException.

The main point here is that it's comparing keys, but you're casting the key (ie: a String) into a Person.

Upvotes: 1

Related Questions