java重写hashcode方法以返回类中变量的hashcode
class UserScoring implements Comparable<UserScoring> {
User user;
int score;
UserScoring(User user, int score) {
this.user = user;
this.score = score;
}
@Override
public int compareTo(UserScoring o) {
if (this.score < o.score) {
return 1;
}
else if (this.score == o.score) {
return 0;
}
return -1;
}
@Override
public int hashCode() {
return user.hashCode();
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UserScoring other = (UserScoring) obj;
return user.equals(other.user);
}
}
我想创建一个类UserScoring
,它可以根据其可变分数进行排序,其唯一性由用户决定
这意味着:
- 如果我使用集合对UserScoring对象集合进行排序。sort(),我希望根据分数按降序排序。我已经覆盖了相同的compareTo方法李>
- 若我创建了一组UserScoring对象,我不想要同一用户的两个UserScoring对象。我已经重写了equals和hashcode方法李>
我有两个疑问: 1.返回与用户对象相同的UserScoring对象的哈希代码是否错误。在我看来,这的确是不对的。但它会导致什么问题呢
当试图添加同一用户的两个UserScoring对象时,是否有任何方法可以确保只有分数较高的UserScoring对象保留在集合中(分数较低的对象要么被逐出,要么不被添加)
UserScoring us1 = new UserScoring(u1, 1000); UserScoring us2 = new UserScoring(u1, 100); Set<UserScoring> set = new HashSet<>(); set.add(us1); set.add(us2);
此集合如何包含us1而不是us2
# 1 楼答案
这没有错。在这种情况下,我们说
UserScoring
对象的“标识”是关联的User
对象。然而,这要求equals()
方法也必须遵守这个身份约定,因此它必须作为return Objects.equal( this.user, other.user )
实现我不认为有任何方法可以使用未修改的哈希集来自动执行此操作,但您可以提供自己的
Set
装饰器(称之为RankingSet
),它根据底层Set
中已经存在的对象检查正在添加的对象,并保持较高级别的对象。(你的排名就是分数。)你可以在interwebz中寻找一个CollectionDecorator,你可以用它来减少你需要做的工作量:它只允许你重写add()
方法,并让剩下的方法被委托给基础集合由于需要能够比较
UserScoring
对象,因此可能会遇到的另一个问题是equals()
方法与Comparable.compareTo()
返回的结果不一致。克服这一问题的一种方法是不使UserScoring
具有可比性,而是实现一个单独的Comparator
,它根据UserScoring
对象的分数对其进行比较(因此,
RankingSet
需要接收这样一个Comparator
作为构造函数参数。)