正确使用Map,只需要正确实现 hashCode()
和 equals()
就行了吗?
如果使用的是HashMap,那么只需要正确实现 hashCode()
和 equals()
就够了。
如果换成TreeMap,正确实现 hashCode()
和 equals()
,结果并不一定正确。
class Student implements Comparable<Student> {
final String name;
final int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int hashCode() {
return Objects.hash(name, score);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Student) {
Student o = (Student) obj;
return Objects.equals(this.name, o.name) && this.score == o.score;
}
return false;
}
@Override
public int compareTo(Student o) {
return this.score < o.score ? -1 : 1;
}
}
先用 HashMap
测试
Map<Student, Integer> map = new HashMap<>();
map.put(new Student("xiaoming", 1), 1);
map.put(new Student("xiaohong", 2), 2);
System.out.println(map.get(new Student("xiaoming", 1)));
System.out.println(map.get(new Student("xiaohong", 2)));
输出为1、2。
改为 TreeMap
再测试:
Map<Student, Integer> map = new TreeMap<>();
输出为null、null、null!
原因:
JDK的TreeMap文档,注意到这句话:
This is so because the Map interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using its compareTo (or compare) method
意思是,Map接口定义了使用 equals()
判定key是否相等,但是SortedMap却使用 compareTo()
来判断key是否相等,而TreeMap是一种SortedMap。
决问题的关键是正确实现 compareTo()
:
@Override
public int compareTo(Student o) {
int n = Integer.compare(this.score, o.score);
return n != 0 ? n : this.name.compareTo(o.name);
}
评论区