The following code should print 3 persons, but it actually print 4 persons, why? Person("a", 1) and Person("a", 4) should be treated as the same, but they are not.
import java.util.TreeSet;
public class Person implements Comparable<Person>{
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String name;
public int age;
@Override
public int compareTo(Person o) {
if(this.name.equals(o.name)){
return 0;
}else if(this.age <= o.age){
return -1;
}else {
return 1;
}
}
@Override public boolean equals(Object other) {
return name.equals(((Person)other).name);
}
@Override public int hashCode() {
return age * 31;
}
public static void main(String[] args) {
TreeSet<Person> persons = new TreeSet<Person>();
persons.add(new Person("a", 1));
persons.add(new Person("b", 3));
persons.add(new Person("c", 2));
persons.add(new Person("a", 4));//This should be ignored.
/*Here should print the first 3 persons, but it prints 4 persons*/
for(Person h: persons){
System.out.println(h.name + ":" +h.age);
}
}
}
Result:
a:1
c:2
b:3
a:4
The problem is the compareTo
method, which performs comparisons based on age, but determines equality based on the Person's name, making it inconsistent with itself.
After inserting the first 3 Persons
, the tree looks something like this (forgive the poor ASCII art):
(c,2)
|
/\
(a,1) (b,3)
Then (a,4) is inserted, it's compared to (c,2) based on the age. The age (4) is bigger than (2), so we go to the right. The next comparison is with (b,3). (a,4) is again bigger, so it's added as a new node to the tree (since there's nothing else to compare to). If instead of adding (a,4) you'd add (a,0), then there would be a comparison with (a,1), and the result would be:
a:1
c:2
b:3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With