简体   繁体   中英

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.

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. I have overriden the compareTo method for the same.
  2. If I create a set of the UserScoring objects, I do not want two UserScoring objects of the same user. I have overriden the equals and the hashcode method for the same.

I have two doubts here: 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?

  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 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?

  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?

It is not wrong. In this case, we say that the "identity" of the UserScoring object is the associated User object. 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 ) .

  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.

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. (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

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() . 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.

(So, the RankingSet would need to receive such a Comparator as a constructor parameter.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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