1

What is the best practice to return a value for hashCode() method if custom field used in equals are null ?

I have a situation, where equals() override is implemented using custom fields. Usually it is recommented to override hashCode() using that custom fields used in equals(). But if all the custom fields used in equals() are null, then what would be the best implementation for hashCode()?

Example:

class Person {
    private String firstName;
    private String lastName;        
    public String getFirstName() {
        return firstName;
    }        
    public String getLastName() {
        return lastName;
    }
    @Override
    public boolean equals(Object object) {
        boolean result = false;
        if (object == null || object.getClass() != getClass()) {
            result = false;
        } else {
            Person person = (Person) object;
            if (this.firstName == person.getFirstName()
                && this.lastName == tiger.getLastName()) {
                result = true;
            }
        }
        return result;
    }        
    @Override
    public int hashCode() {
        int hash = 3;
        if(this.firstName == null || this.lastName == null) {
            // <b>What is the best practice here, </b>
            // <b>is return super.hashCode() better ?</b>
        }        
        hash = 7 * hash + this.firstName.hashCode();
        hash = 7 * hash + this.lastName.hashCode();
        return hash;
    }
}
  1. is it required to check for null in hashCode() ?
  2. If yes, what should be returned if custom values are null ?
1
  • 1
    Use equals to compare strings, not ==. – WilQu Jun 5 '14 at 14:47
3

If you can guarantee through your code that firstName and lastName are never null, there is no reason to test for it.

  • Its possible that these values are only set in the constructor and there is no setter for it. In that case, they are never null.

  • Or it may be that you have a setter that checks for null and populates an empty string if a null is passed in

In either of those cases, you can guarantee that the values are always not null and thus don't need to test for it.

Doing this will drastically simplify the amount of thought needed to reason about the code and is probably the right way to go about implementing the code.

If you do allow for nulls in the values, you could just say that the hash of the value is 0. Based on your previous code:

@Override
public int hashCode() {
    int hash = 3;
    int firstHash = 0;
    int lastHash = 0;
    if(this.firstName != null) {
        firstHash = this.firstName.hashCode();
    }
    if(this.lastName != null) {
        lastHash = this.lastName.hashCode();
    }

    hash = 7 * hash + firstHash;
    hash = 7 * hash + lastHash;
    return hash;
}

hashCode isn't trying to be a cryptographically secure hash - its just trying to make it so you don't have everything colliding in a HashMap and have it degenerate to a linked list.

You may be interested in the @NotNull annotation which puts a compile time requirement on this. This was implemented as part of JSR 308... but thats something for Java 8.

1

I would do hashCode() as follows

public int hashCode() { String str = this.firstName + " " + this.lastName; return str.hashCode(); }

That would satisfy the requirements for hashCode() equal objects have same hashCode()

Doesn't have any null problem at all.

3
  • 1
    So you're willing to pay the price of string concatenation for every test against a hash table? – kdgregory Jun 5 '14 at 12:30
  • You are right, we need to manually check the null to have the best performance. – InformedA Jun 5 '14 at 17:35
  • Uhh Ohh, I just realize Eclipse has generate hashCode() and equals(). Never really have to touch things this low-level at work, I can't believe I miss an Eclipse's feature like this. – InformedA Jun 5 '14 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.