Item-9: “Always override hashCode() when you overr

2019-09-01 06:08发布

问题:

With respect to 3 contracts mentioned below:

1) Whenever hashCode() is invoked on the same object more than once during an execution of an application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

From this statement, i understand that, In a single execution of an application, if hashCode() is used one or more times on same object it should return same value.

2) If two objects are equal according to the equals(Object) method, then calling the hashCode() method on each of the two objects must produce the same integer result.

From this statement, i understand that, to perform the equality operation(in broad scope) in your subclass, There are at least four different degrees of equality.

(a) Reference equality(==), comparing the internal address of two reference type objects.

(b) Shallow structural equality: two objects are "equals" if all their fields are ==. { For example, two SingleLinkedList whose "size" fields are equal and whose "head" field point to the same SListNode.}

(c) Deep structural equality: two objects are "equals" if all their fields are "equals". {For example, two SingleLinkedList that represent the same sequence of "items" (though the SListNodes may be different).}

(d) Logical equality. {Two examples: (a) Two "Set" objects are "equals" if they contain the same elements, even if the underlying lists store the elements in different orders. (b) The Fractions 1/3 and 2/6 are "equals", even though their numerators and denominators are all different.}

Based on above four categories of equality, second contract will hold good only: if(Say) equals() method returns truth value based on logical_equality between two objects then hashCode() method must also consider logical_equality amidst computation before generating the integer for every new object instead of considering internal address of a new object.

But i have a problem in understanding this third contract.

3) IT IS NOT REQUIRED that if two objects are unequal according to the equals(Object) method, then calling the hashCode() method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

In second contract, As we are saying that hashCode() method should be accordingly[for ex: considering logical_equality before generating integer] implemented, I feel, It is not true to say that, if two objects are unequal according to equals(Object) then hashCode() method may produce same integer results as mentioned in third contract? As per the argument in second contract, hashCode() must produce distinct integer results. One just writing return 42 in hashCode() is breaking second contract!

please help me understand this point!

回答1:

It would be impossible for hashCode() to always return different values for unequal objects. For example, there are 2^64 different Long values, but only 2^32 possible int values. Therefore the hashCode() method for Long has to have some repeats. In situations like this you have to try hard to ensure that your hashCode() method distributes values as evenly as possible, and is unlikely to produce repeats for the instances you are most likely to use in practice.

The second condition just says that two equal() instances must return the same hashCode() value, so this program must print true:

Long a = Long.MIN_VALUE;
Long b = Long.MIN_VALUE;
System.out.println(a.hashCode() == b.hashCode()); // a.equals(b), so must print true.

However this program also prints true:

Long c = 0L;
Long d = 4294967297L;
System.out.println(c.hashCode() == d.hashCode()); // prints true even though !c.equals(d)


回答2:

hashCode() does not have to produce a distinct result. return 0; is a perfectly legal implementation of hashCode() - it ensures that two equal objects will have the same hash code. But it will ensure dismal performance when using HashMaps and HashSets.

It's preferable that hashCode() return values will be distinct (i.e., objects that are not equal should have different hash codes), but it's not required.



回答3:

The second contract states what happens when equals() returns true. It does not say anything about the case when equals() returns false.

The third contract is just a reminder about that fact. It reminds you that when equals() is false for two objects, there is no connection between their hash codes. They may be same or different, as the implementation happens to make them.



回答4:

The third point means that you can have many unequal objects with the same hashcode. . For example 2 string objects can have the same hashcode. The second point states that two equal objects must have the same hashcode. . return 5 is a valid hash implementation because it returns the same value for 2 equal objects.



标签: java equals