开发者

Hashcode contract in java?

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified

Above statement is written at http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode() under hashcode contract.

开发者_JAVA百科I have a question on statement i.e

provided no information used in equals comparisons on the object is modified

Even if we modify equals method still hashcode will return the same integer . so howcome hash code value is dependent on objects equal comparison.


Good question. From equals() documentation,

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.


You are adding extra meaning to that statement that is not there. It does not say that hashCode WILL change if the evaluation of equals changes. It is saying hashCode MAY change if the evaluation of equals changes. It is no longer guaranteed that the hashCode will be the same afterward. It is not wrong if it still is!

Remember

@Override
public int hashCode() {
    return 1;
}

is a completely legal implementation of hashCode() that meets all requirements set forth by the documentation. hashCode is not, by definition, dependent on the equals calculation.

In practice they will of course be coupled together. Normally you override hashcode using all the same fields used as in equals because it is necessary that two different objects whose equals are true have the same hashCode. And return 1; wouldn't play very nice with any of the classes that actually rely on the hashCode() method.

This more fully formed example of a legal implementation of hashCode that sometimes changes when equals changes, but not always, may be more clear.

public class MakesHashMapsSlow {

    private String value;
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MakesHashMapsSlow other = (MakesHashMapsSlow) obj;
        if ((this.value == null) ? (other.value != null) : !this.value.equals(other.value)) {
            return false;
        }
        return true;
    }
    @Override
    public int hashCode() {
        if (value == null || value.isEmpty()) {
            return 0;
        } else {
            return value.charAt(0);
        }
    }
}


This means that, if no one of the object properties (see: instance variables that shouldn't be considered transient) is modified, then equals should give the same result, and hashcode should behave accordingly (be the same for the object).

Practical example:

class Pair {
   public int x, y;
   public int hashCode(); // computes hashcode based on both x and y
}

Pair p = new Pair(3,10);
int h1 = p.hashCode();
// program does something but pair is still (3,10)
int h2 = p.hashCode();
assert(h1 == h2)

The principle is that hash code must change if equals comparison result changes and vice versa. This usually means that all the variables taken into account when comparing two items should be considered when computing the hashcode, so that if something changes, this change is relflected both on comparisons and on hashcodes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜