简体   繁体   English

覆盖哈希码方法以返回类中变量的哈希码

[英]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);
        }
    }

I want to create a class UserScoring which can be sorted on the basis of its variable score and whose uniqueness is determined by its user. 我想创建一个UserScoring类,可以根据其可变分数对其排序,并且其唯一性由其用户确定。

This means that : 这意味着 :

  1. If I sort a collection of UserScoring objects using Collections.sort(), I want the sorting based on score in a descending order. 如果我使用Collections.sort()对UserScoring对象的集合进行排序,则希望基于分数按降序排序。 I have overriden the compareTo method for the same. 我已经重写了compareTo方法。
  2. If I create a set of the UserScoring objects, I do not want two UserScoring objects of the same user. 如果创建一组UserScoring对象,则不需要同一个用户的两个UserScoring对象。 I have overriden the equals and the hashcode method for the same. 我已经覆盖了equals和hashcode方法。

I have two doubts here: 1. Is it wrong to return the hashcode of the UserScoring object the same as the User object. 我在这里有两个疑问:1.返回与用户对象相同的UserScoring对象的哈希码是否错误。 It sure looks wrong to me. 在我看来,这肯定是错的。 But what are the problems it can cause? 但是它会引起什么问题呢?

  1. Is there any way at all to make sure that only the UserScoring object of the higher score is kept in the set(and the object with less score is either evicted or not added) whenever there is an attempt to add two UserScoring objects of the same user. 是否有任何方法可以确保在尝试添加两个相同的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); 

How can this set contain us1 instead of us2? 这个集合如何包含us1而不是us2?

  1. Is it wrong to return the hashcode of the UserScoring object the same as the User object. 返回与用户对象相同的UserScoring对象的哈希码是否错误。 It sure looks wrong to me. 在我看来,这肯定是错的。 But what are the problems it can cause? 但是它会引起什么问题呢?

It is not wrong. 没错 In this case, we say that the "identity" of the UserScoring object is the associated User object. 在这种情况下,我们说UserScoring对象的“身份”是关联的User对象。 However, this requires that your equals() method must also honor this identity convention, so it must be implemented as return Objects.equal( this.user, other.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. 是否有任何方法可以确保在尝试添加同一用户的两个UserScoring对象时,将得分较高的UserScoring对象保留在集合中。

I do not think there is any way to automate this with an unmodified HashSet, but you can provide your own Set decorator (call it, say, RankingSet ) which examines the object being added against the object already in the underlying Set and keeps the one with the higher rank. 我不认为有任何方法可以使用未经修改的HashSet来自动执行此操作,但是您可以提供自己的Set装饰器(称其为RankingSet ),该装饰器针对基础Set已经存在的对象检查要添加的对象并保留其中一个排名较高。 (The rank in your case being the score.) You can look around the interwebz for a CollectionDecorator that you can use to reduce the amount of work that you need to do: it will enable you to only override the add() method and let the rest of the methods be delegated to the underlying Set (在您的情况下,排名是得分。)您可以在interwebz上查找CollectionDecorator,该集合可用于减少所需做的工作:它将使您仅覆盖add()方法并让其余方法将委托给基础Set

Since you need to be able to compare your UserScoring objects, another problem you are likely to run into is that your equals() method does not agree with the result returned by Comparable.compareTo() . 由于您需要能够比较UserScoring对象,因此您可能会遇到的另一个问题是equals()方法与Comparable.compareTo()返回的结果不一致。 One way to overcome this is by not making UserScoring comparable, and instead implementing a separate Comparator which compares UserScoring objects based on their score. 解决此问题的一种方法是使UserScoring具有可比性,而是实现一个单独的Comparator ,该UserScoring根据用户的得分比较UserScoring对象。

(So, the RankingSet would need to receive such a Comparator as a constructor parameter.) (因此, RankingSet需要接收这样的Comparator作为构造函数参数。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM