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
,该类可以根据其可变得分进行排序,其唯一性由其用户确定。这意味着 :
如果我使用Collections.sort()对UserScoring对象的集合进行排序,则希望基于分数按降序排序。我已经重写了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?
最佳答案
返回与用户对象相同的UserScoring对象的哈希码是否错误。在我看来,这肯定是错的。但是它会引起什么问题呢?
没错在这种情况下,我们说UserScoring
对象的“身份”是关联的User
对象。但是,这要求您的equals()
方法还必须遵守此身份约定,因此必须将其实现为return Objects.equal( this.user, other.user )
。
有什么方法可以确保在尝试添加同一用户的两个UserScoring对象时,将得分较高的UserScoring对象保留在集合中。
我认为没有任何方法可以使用未经修改的HashSet来自动执行此操作,但是您可以提供自己的Set
装饰器(调用它,例如RankingSet
),该装饰器将针对正在添加的对象与基础并保持较高的排名。 (在您的情况下,排名是得分。)您可以在interwebz上查找CollectionDecorator,该集合可用于减少所需做的工作:它将使您仅覆盖Set
方法并使其余方法将委托给基础Set
由于您需要能够比较add()
对象,因此您可能会遇到的另一个问题是UserScoring
方法与equals()
返回的结果不一致。解决此问题的一种方法是不使Comparable.compareTo()
具有可比性,而是实现一个单独的UserScoring
,该Comparator
根据其得分比较UserScoring
对象。
(因此,RankingSet
需要接收这样的Comparator
作为构造函数参数。)