一直没搞懂TreeSet是怎么判断重复元素的,有人说是先调用compareTo()方法,如果返回0,就判断为重复元素。于是我写了一个学生类,下面是各种方法
//重写hashCode()
public int hashCode(){
return this.num.hashCode();
}
//重写equal()
public boolean equals(Object o){
Student stu = (Student)o;
if(this.num.equals(stu.num) == true){
return true;
}else{
return false;
}
}
//重写compareTo(T o)
@Override
public int compareTo(Student stu) {
float thisAllScore = this.getChinese()+this.getMath()+this.getEnglish();
float stuAllScore = stu.getChinese()+stu.getMath()+stu.getEnglish();
if(this.hashCode() == stu.hashCode()){
return 0;
}else if(this.equals(stu) == true){
return 0;
}else if(thisAllScore < stuAllScore){
return 1;
}else if(thisAllScore > stuAllScore){
return -1;
}else{
return 1;
}
}
然后添加5个Student
Student stu1 = new Student("张三", "01", 85.0f, 92.0f, 97.0f);
Student stu2 = new Student("李四", "02", 78.0f, 95.5f, 87.0f);
Student stu3 = new Student("王五", "03", 89.0f, 80.5f, 93.0f);
Student stu4 = new Student("李六", "04", 96.5f, 82.5f, 83.0f);
Student stu5 = new Student("李六", "04", 196.5f, 82.5f, 83.0f);
allStu.add(stu1);
allStu.add(stu2);
allStu.add(stu3);
allStu.add(stu4);
allStu.add(stu5);
输出结果
-----------------排名-----------------
|1|04|李六|196.5|82.5|83.0|362.0|
|2|01|张三|85.0|92.0|97.0|274.0|
|3|03|王五|89.0|80.5|93.0|262.5|
|4|04|李六|96.5|82.5|83.0|262.0|
|5|02|李四|78.0|95.5|87.0|260.5|
stu4.getNum().hashCode() = 1540
stu5.getNum().hashCode() = 1540
stu4.equals(stu5) = true
stu4跟stu5的num的哈希码相同,equals返回true.
但是还是同时出现了,这是为什么呢
------解决方案--------------------
TreeSet在调用add的时候会调用compareTo方法排序
LZ可以试试把hashCode和equals方法注释掉,然后把compareTo直接return 0,最终应该只有一条记录
所以问题在于,add自动调用compareTo的时候,采用2分法去比较
当add(stu3)结束时,排序结果是 stu1,stu3,stu2
当add(stu4)的时候,会先比较stu4和allStu的中间的元素sut3,而stu4比stu3小,继续和stu3之后元素比较,stu4比stu2大,所以add(stu4)结束后,排序是 stu1,stu3,stu4,stu2
接着add(stu5)的时候,2分法,stu5先和stu3比较,而stu5比stu3大,所以继续和stu1比较,此时stu5没有能和stu4比较,所以就算stu4和stu5的hashCode和equals都返回0,因为不发生比较就不能判断是同一个元素,所以stu5就被排到最前面,所以就发生了stu4和stu5同时出现了。