tags:

views:

751

answers:

9

I have a very simple class with only one field member (e.g. String). Is it OK to implement hashCode() to simply return fieldMember.hashCode()? Or should I manipulate the field's hash code somehow? Also, if I should manipulate it, why is that?

+2  A: 

Yeah, that's pretty standard. And if the class reflects a database row, I just return the primary key.

Paul Tomblin
+10  A: 

If fieldMember is a pretty good way to uniquely identify the object, I would say yes.

bobwienholt
+8  A: 

Joshua Bloch lays out how to properly override equals and hashCode in "Effective Java" Chapter 3.

duffymo
Thank you. I had read a summary of it, but it didn't answer my question. If I follow his rules, I'll return `37 * field.hashCode() + c`, but is this really needed? Is the field's hash code not sufficient?
Hosam Aly
Assuming that the field is not a primitive. You didn't say if it was an object or a double, so I thought the reference would be worth having. You also didn't mention overriding equals, and you should.
duffymo
The field's hash code should be sufficient. If it's a primitive, for example int: Integer.valueOf(fieldValue).hashCode()
armandino
@armandino: This could be a nice way to do it for primitives (except for the cost of creating a new integer for values > 127), but for an int it's sufficient to return its value. That's the implementation of Integer.hashCode(), and it makes sense because it would be perfectly distributed.
Hosam Aly
A: 

Ya. It is good programming practice. I normally use:

return var ^ 1;

Techmaddy
That's the heart of my question: do I need to combine it with something else? You're xor-ing it with 1, so does this mean that the field's hash code is not sufficient?
Hosam Aly
The randomness of (var) and (var ^ 1) are the same. I wouldn't bother doing this.
Peter Lawrey
+1  A: 

There are only two real requirements for hashCode: one, that equals instances have equal hash codes, and two, that hashCode runs reasonably fast. The first requirement is the most important one in practice; without it, you could put something into a collection but not find it there. The second is simply a performance issue.

If the hash code algorithm of your field meets the above, then its algorithm also works for your class, if your class equals also depends solely on whether those fields are equals.

Paul Brinkley
You left out one requirement: Objects that are not equal usually have different hash codes.
Darron
I thought about that. Thing is, if they have different hash codes, that's great, but if they don't, that's often fine, too (and in practice, always unavoidable). Hash collisions just make searches a tad longer, whereas the other case is an honest-to-god failure.
Paul Brinkley
+3  A: 

Multiplying, adding, or xor-ing things will not make it more unique. Mathematically, you'd be applying constant functions to a single variable, which does not increase the number of possible values of the variable.

That sort of technique is useful for combining multiple hashcodes and still keeping the risk of collisions relatively small; it has no bearing whatever on a single hashcode.

Michael Myers
Thank you. I am not particularly strong in mathematics, but couldn't applying a constant function to a value enhance it (or decrease possible collisions)?
Hosam Aly
I don't know what you mean by enhancement here (unless it's collision avoidance), but if two hashcodes are the same, and you do the same operation to them, they will still be equal and still collide.
David Thornley
@David Thornley: Exactly.
Michael Myers
Hosam Aly
@Hosam Aly: HashMap uses the hash as an index to the array of buckets, so it uses its supplemental hash to reduce the risk of collision. This doesn't expand the number of possible hashes, but spreads the existing hash codes further apart in the bit positions that HashMap uses for indexing.
Michael Myers
(cont.) This is why David Thornley mentioned collision avoidance in his comment above. Without hash(), a bad hashCode implementation could give the HashMap close to O(n) performance, instead of O(1). The comments on the hash() method basically say what I've been saying, but I hope I made it clearer.
Michael Myers
+1  A: 

If 'fieldMember' variable already implements 'hashCode' function then you can use it directly from your parent class. If 'fieldMember' variable is a custom class instance, then you must implement it correctly by yourself. Read java.lang.Object API documentation as guideline to implement 'hashCode'.

gedevan
A: 

Usually, unless you are using this object as the key for a *HashMap or an element in a *HashSet, hashCode() doesn't need to be overridden.

Peter Lawrey
I expect it to be used in a HashMap, so I do need to override it.
Hosam Aly
A: 

As someone else mentioned, you should follow the advice in Effective Java. If you override the hashCode() method, you should also be overriding the equals() method. Furthermore, the two methods should be consistent.

To simplify writing good equals() and hashCode() methods, I use EqualsBuilder and HashCodeBuilder from Apache Commons Lang

Here are examples:

public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    User other = (User) o;
    return new EqualsBuilder()
            .append(this.getUniqueId(), other.getUniqueId())
            .isEquals();
}

public int hashCode() {
    return new HashCodeBuilder()
            .append(this.getUniqueId())
            .toHashCode();
}
Jeff Olson
Thank you @Jeff, but this is probably overkill for my simple object.
Hosam Aly
I'm not sure I agree it's overkill; I use this approach on all my domain classes, even the simplest ones. And simple classes have a tendency to become more complicated over time! :)
Jeff Olson