0

The following code throws a ClassCastException when I try to get a mapping with my custom Dog class as the key:

import java.util.TreeMap;

public class testMain {
        public static void main(String[] args) {

            TreeMap<Dog, String> m = new TreeMap<Dog, String>();
            m.put(new Dog("Fido"), "woof");

            // this line produces a ClassCastException
            String sound = m.get(new Dog("Fido"));

            System.out.println(sound);
    }
}

The dog class is simply:

public class Dog {

    String name;

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

I don't see why TreeMap would be casting the Dog class in the first place. Why do I get a ClassCastException when using a custom made class as the key? Any ideas on how to fix this code would be appreciated as well!

tshepang
  • 12,111
  • 21
  • 91
  • 136
chessofnerd
  • 1,219
  • 1
  • 20
  • 40
  • And implement `equals` and `hashCode()` because otherwise you will not be able to retrieve the entry. – SJuan76 Jun 13 '13 at 15:45

3 Answers3

4

TreeMap sorts elements in insertion time according to ordering of their keys. Hence the objects that are used as keys must implement Comparable interface.

Please refer to an edit I have made to your Dog class. It works now:

public static class Dog implements Comparable<Dog> {

    String name;

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public int compareTo(Dog obj) {
        return name.compareTo(obj.name);
    }
}

EDIT: The reason for ClassCastException exception:

If you see the line Comparable<? super K> k = (Comparable<? super K>) key; in the code of the get method of the TreeMap you will see that it's trying to cast your key to Comparable object. Your object was not an instanceof Comparable.

final Entry<K,V> getEntry(Object key) {
     // Offload comparator-based version for sake of performance
     if (comparator != null)
         return getEntryUsingComparator(key);
     if (key == null)
         throw new NullPointerException();
     Comparable<? super K> k = (Comparable<? super K>) key;
     Entry<K,V> p = root;
     while (p != null) {
         int cmp = k.compareTo(p.key);
         if (cmp < 0)
             p = p.left;
         else if (cmp > 0)
             p = p.right;
         else
             return p;
     }
     return null;
 }
darijan
  • 9,725
  • 25
  • 38
  • Thanks, I'm still confused why the `ClassCastException` would arise in the first place though. Why not something like a `YouGotToImplementComparable` exception? How does this error have anything to do with casting? – chessofnerd Jun 13 '13 at 15:47
  • 3
    You get a `ClassCastException` because the `TreeMap` tries to cast your custom class to `comparable` interface so that it can call `compareTo` method on it. Since you didn't implement the `Comparable` interface the casting gives error. – Mubin Jun 13 '13 at 15:52
1

Dog must implement Comparable if you want to use it as key in a TreeMap without a Comparator

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0

You have to let your Dog classes implements the Comparable interface.

class Dog implements Comparable<Dog>

From the doc :

The map is sorted according to the natural ordering of its keys

Alexis C.
  • 91,686
  • 21
  • 171
  • 177