简体   繁体   中英

Combining Hash of String and Hash of Long

I have the following java class:

public class Person{
   String name;  //a unique name
   Long DoB;     //a unique time
   .
   .
   .
   @Override
   public int hashCode(){
     return name.hashCode() + DoB.hashCode();
   }

}

Is my hashCode method correct (ie would it return a unique number of all combinations.

I have a feeling I'm missing something here.

您可以让java.util.Arrays为您做这件事:

return Arrays.hashCode(new Object[]{ name, DoB });

Aside for the obvious, which is, you might want to implement the equals method as well...

  • Summing two hash codes has the very small risk of overflowing int
  • The sum itself seems like a bit of a weak methodology to provide unique hash codes. I would instead try some bitwise manipulation and use a seed.

You might also want to use something more fluent and more NPE-bulletproof like Google Guava :

@Override
public int hashCode(){
    return Objects.hashCode(name, DoB);
}

@Override
public boolean equals(Object o) {
    if ( this == o ) {
        return true;
    }
    if ( o == null || o.getClass() != Person.class ) {
        return false;
    }
    final Person that = (Person) o;
    return Objects.equal(name, that.name) && Objects.equal(DoB, that.DoB);
}

Edit:

IntelliJ IDEA and Eclipse can generate more efficient hashCode() and equals() .

usually a hashcode is build like so:

   @Override
   public int hashCode(){
     return name.hashCode() ^ DoB.hashCode();
   }

but the important thing to remember when doing a hashcode method is the use of it. the use of hashcode method is to put different object in different buckets in a hashtable or other collection using hashcode. as such, it's impotent to have a method that gives different answers to different objects at a low run time but doesn't have to be different for every item, though it's better that way.

This hash is used by other code when storing or manipulating the instance – the values are intended to be evenly distributed for varied inputs in order to use in clustering. This property is important to the performance of hash tables and other data structures that store objects in groups ("buckets") based on their computed hash values

and

The general contract for overridden implementations of this method is that they behave in a way consistent with the same object's equals() method: that a given object must consistently report the same hash value (unless it is changed so that the new version is no longer considered "equal" to the old), and that two objects which equals() says are equal must report the same hash value.

See Bloch's Effective Java #9.

But you should start with an initial value (so that subsequent zero values are significant), and combine the fields that apply to the result along with a multiplier so that order is significant (so that similar classes will have much different hashes.)

Also, you will have to treat things like long fields and Strings a little different. eg, for longs:

(int) (field ^ (field>>>32))

So, this means something like:

@Override public int hashCode() {
   int result = 17;
   result += name.hashCode() == null ? 0 : name.hashCode();
   result = 31 * result + (int) (DoB ^ (DoB >>> 32));
   return result;
}

31 is slightly magic, but odd primes can make it easier for the compiler to optimize the math to shift-subtraction. (Or you can do the shift-subtraction yourself, but why not let the compiler do it.)

Your hash code implementation is fine and correct. It could be better if you follow any of the suggestions other people have made, but it satisfies the contract for hashCode , and collisions aren't particularly likely, though they could be made less likely.

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