将 hashcode 方法覆盖到 return class 中变量的 hashcode

Overriding hashcode method to return hashcode of variable in a class

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);
        }
    }

我想创建一个 class UserScoring,它可以根据其可变分数进行排序,其唯一性由其用户确定。

这意味着:

  1. 如果我使用 Collections.sort() 对 UserScoring 对象的集合进行排序,我希望根据分数降序排序。我已经覆盖了相同的 compareTo 方法。
  2. 如果我创建一组 UserScoring 对象,我不想要同一用户的两个 UserScoring 对象。我已经覆盖了相同的 equals 和 hashcode 方法。

这里我有两个疑惑: 1. returnUserScoring对象的hashcode和User对象一样是不是错了。这对我来说肯定是错误的。但是它会导致什么问题呢?

  1. 有什么方法可以确保只有分数较高的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. Is it wrong to return the hashcode of the UserScoring object the same as the User object. It sure looks wrong to me. But what are the problems it can cause?

没有错。在这种情况下,我们说 UserScoring 对象的 "identity" 是关联的 User 对象。但是,这要求您的 equals() 方法也必须遵循此标识约定,因此它必须实现为 return Objects.equal( this.user, other.user ).

  1. Is there any way at all to make sure that the UserScoring object of the higher score is kept in the set whenever there is an attempt to add two UserScoring objects of the same user.

我认为没有任何方法可以使用未修改的 HashSet 来自动执行此操作,但您可以提供自己的 Set 装饰器(称其为 RankingSet),它会检查正在检查的对象针对已经在基础 Set 中的对象添加,并保留排名较高的对象。 (你的排名是分数。)你可以在 interwebz 周围寻找一个 CollectionDecorator ,你可以使用它来减少你需要做的工作量:它将使你能够只覆盖 add() 方法并让其余的方法委托给底层的 Set

由于您需要能够比较您的 UserScoring 对象,您可能 运行 遇到的另一个问题是您的 equals() 方法与返回的结果不一致Comparable.compareTo()。克服这个问题的一种方法是 not 使 UserScoring 具有可比性,而是实现一个单独的 Comparator 来比较 UserScoring 对象基于他们的分数。

(因此,RankingSet 需要接收这样的 Comparator 作为构造函数参数。)