Domanda

I am getting ClassCastException error. This error occurs when I insert the object that is derived from a class I have created. My code is below: When I run, I always get ClassCastException error. Also, the comparator of my class is shown as null in debugger.

I have written a comparator (as far as I know) and overridden necessary methods.

How can I use a Set<> with a class that I have created and use contains() method?

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

I have managed to get rid of the error. But now, the output is "does not contain".

È stato utile?

Soluzione

What I am about to suggest has nothing to do with ClassCastException, which is thrown simply because you are checking contains with an int argument on a set of objects of type Person ... short answer: you can't cast an object to a subclass of which it is not an instance. Even the javadoc says exactly that.

For situations like this, I really like to use Guava predicates. A predicate allows you to apply a boolean condition to any iterable, returning those elements that satisfy the specified condition. In your example, you can define predicates that return the subset of people of whatever age you want.

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

Hope this helps.

Altri suggerimenti

I assume that your class Adjacent implements Comparable interface based on your code. And your class contains a method called getID(). So therefore when you override the compareTo() method, you want to make sure that the object comparison makes sense. I'm not sure what your getID() returns. But it seems like integer. So you might want to change the implementation of compareTo() as follows:

@Override
public int compareTo(Adjacent adj) {

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

So this way the comparison will return negative/zero/positive depending on the ID comparison of two Adjacent class objects.

Also in your overrided equals() method, the implementation is incorrect because two objects are not necessarily equal even if they have the same hash code. A good example of overriding equals and hashCode methods is given in another SO post. Also, in your case, I think you probably don't even need to override equals method since your class implements Comparable interface already.

Don't call contains with a parameter that's a different type; this behavior is actually documented. The contains() method is a non-generic method for legacy reasons, and it's not safe if you're using a TreeSet. If you implement hashCode() and equals() and switch to a HashSet, your problems will go away.

Do you really need people sorted by age?

Edit: I see what you're trying to do, now. You don't want a Set, you want Map<Integer, Collection<Person>>, or just a single pass loop to look for the given age.

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

or

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)) ...
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top