Objects as Map keys without Hashcode and equals
public class Contact
{
int i;
String name;
public Contact(int iVal, String nameVal)
{
i = iVal;
name = nameVal;
}
}
public class MultiMap
{
public static void main (String args[])
{
java.util.HashMap m = new java.util.HashMap();
Contact m1 = new Contact(1, "name");
Contact m2 = new Contact(1, "name");
m.put(m1, "first");
m.put(m2, "second");
System.out.println(m.get(m1));
System.out.println(m.get(m2));
}
}
Output is:
first
second
How does this "get" method behave ? As both m1 and M2 have same values and I have not overridden hashcode(), will Object class's equals() method be called ?
Is this correct ?
- There is no hashcode method so there is no way for the JVM to 开发者_StackOverflow社区see if objects m1 and m2 contain different values
- There is no equals method overridden so Object class's equals() is invoked and as both objects are different the code above works fine without m2 replacing m1's value.
When the hashCode()
and equals(Object o)
methods are not overridden by your class, Java just uses the actual reference to the object in memory to calculate the values (ie. check if it is the same instantiation of the class). That is why you still get both results.
All Objects have hashCode() and equals(). When they are not overridden, the default implementations are used. The default behaviour is to treat all objects as different, unless they are the same object.
For comparison, the IdentityHashMap always does this even if you have overridden you hashCode and equals.
It will use equals and hashcode method of object class to find the value (as Contact does not overide equals and hashcode methods), so yes.
- Yes, Java will always see two Contact objects are different as it will use object reference to compare when it using the equals method in object
- Yes, as two contact objects have to references.
Yes this is correct. Any java object that does not define its own equals and hashcode methods inherit the default equals and hascode methods on java.lang.Object. These default implementation are based on object reference equality and not on logically equality. Since you have called get with the same object reference the object can be returned from the map.
Here is an example that illistrates this further.
java.util.HashMap m = new java.util.HashMap();
Contact m1 = new Contact(1, "name");
Contact m2 = new Contact(1, "name");
m.put(m1, "first");
m.put(m2, "second");
System.out.println(m.get(m1));//first
System.out.println(m.get(m2));//second
System.out.println(m.get(new Contact(1, "name"));//null - since the new object has a different object reference.
Though m1 and m2 have the same values they are different object references.
This is correct : There is no hashcode method so there is no way for the JVM to see if objects m1 and m2 contain different values -> So it uses the Object class's hasCode() method to calculate the hashCode value to execute the get(), which return different hash values(obvious).
the second point is also correct: As you have not implemented your own equals(), will consider Object's equals() which returns true only when one object is compared to itself.
Here in Contact
class you did not implement the hashcode()
and equals()
functions.
When HashMap call these method it will search out for these method in the parent class which is Object in this case.
In this case the object location on the Heap is evaluated instead of the values.
e.g. For two objects o1
and o2
o1.equals(o2) == true
only when o1 == o2
hashCode()
is a method of Object class. Hash code is an integer representation of an object by JVM. Hash code is system generated and JVM takes the address of the object as the basis (seed) to generate the hash code. Hash codes generated need not be the same for different times of execution.
By default Object class override the hashCode and equals method. This is the reason you get the desired output.
If you do not override equals and hashcode method, JVM checks it behind the scene. As m1 and m2 both are different object instances, equals method always return false. i.e :
1. For equals:
m1.equals(m2) //return false because both are different instances.
2. For hashCode: //See the source code inside HashMap.java
HashMap internally uses to rehash the key before putting in hashMap. See bellow.
[![Source code of put method][1]][1]
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
for the rehash, hashMap has it's own static hash method:
[![Source code of hash method][1]][1]
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Internally, both equals and hashCode method work in this way, that is why you get both the values stored in the HashMap.
Hope this helps :)
精彩评论