即使我重写compareTo(),我也得到ClassCastException

时间:2014-02-19 03:29:31

标签: java classcastexception comparator compareto

我收到ClassCastException错误。当我插入从我创建的类派生的对象时,会发生此错误。 我的代码如下: 当我运行时,我总是得到ClassCastException错误。 此外,我的类的比较器在调试器中显示为null。

我写了一个比较器(据我所知)并覆盖了必要的方法。

如何使用Set<>使用我创建的类并使用contains()方法?

public class Person implements Comparable<Person>
{
    int age;
    double height;
    public Person(int age, double height)
    {
        this.age = age;
        this.height = height;
    }
    @Override
    public int compareTo(Person person) 
    {
        return age - person.age;
    }
    public boolean equals(Object obj)
    {
        final Person other = (Person) obj;
        if (this.age == other.age)
            return true;
        return false;
    }
    public static void main(String[] args)
    {
        Set<Person> people = new HashSet<>();
        Person p1 = new Person(10, 1.00);
        Person p2 = new Person(11, 1.10);
        Person p3 = new Person(12, 1.20);
        Person p4 = new Person(14, 1.40);
        people.add(p1);
        people.add(p2);
        people.add(p3);
        people.add(p4);
        if(people.contains(12))
            System.out.println("contains");
        else
            System.out.println("does not contain");
    }
}

我设法摆脱了错误。但现在,输出“不包含”。

3 个答案:

答案 0 :(得分:0)

我假设您的班级Adjacent根据您的代码实现Comparable接口。您的类包含一个名为getID()的方法。因此,当您覆盖compareTo()方法时,您希望确保对象比较有意义。我不确定你的getID()会返回什么。但它似乎是整数。因此,您可能希望更改compareTo()的实现,如下所示:

@Override
public int compareTo(Adjacent adj) {

    return this.getId() - adj.getId();
}

因此,这种比较将返回负/零/正,具体取决于两个Adjacent类对象的ID比较。

同样在你的覆盖equals()方法中,实现是不正确的,因为即使两个对象具有相同的哈希码,它们也不一定相等。覆盖equalshashCode方法的一个很好的例子在another SO post中给出。另外,在您的情况下,我认为您可能甚至不需要覆盖equals方法,因为您的类已经实现了Comparable接口。

答案 1 :(得分:0)

不要使用不同类型的参数调用contains;这种行为实际上是documented。由于遗留原因,contains()方法是一种非泛型方法,如果您使用TreeSet则不安全。如果您实施hashCode()equals()并切换到HashSet,您的问题就会消失。

你真的需要按年龄排序的人吗?

编辑:我现在看到你正在尝试做什么。你不想要Set,你想要Map<Integer, Collection<Person>>,或者只需要一个通过循环来查找给定的年龄。

for (Person p : people) {
    if (p.age == 12) ...;
}

Map<Integer, Set<Person> peopleByAge = new HashMap<Integer, Set<Person>>();
for (Person p : people) {
    if (!peopleByAge.contains(p.age)) {
        peopleByAge.put(p.age, new TreeSet<Person>();
    }
    peopleByAge.get(p.age).add(p);
}

if (people.age.containsKey(12)) ...

答案 2 :(得分:0)

我要建议的内容与ClassCastException无关,而ClassCastException只是因为您在一组contains类型的对象上检查int Person参数而引发的。 ..简答:你不能将一个对象强制转换为一个不是实例的子类。甚至是the javadoc says exactly that

对于这样的情况,我真的很喜欢使用Guava谓词。谓词允许您将boolean条件应用于任何iterable,返回满足指定条件的元素。在您的示例中,您可以定义返回所需年龄的人的子集的谓词。

Predicate<Person> getAgePredicate(final int age) {
    return new Predicate<Person>() {
        public boolean apply(Person p) { return p.age == age; }
    };

}

Set<Person> people = new Hashset<>();
... // populate people
Set<Person> peopleOfAgeTwelve = Sets.filter(people, getAgePredicate(12));

希望这有帮助。