在以前看java书的时候得知如果向hashmap中添加元素的时候要先计算hashcode然后算出一个index,如果index位置上没有元素则添加该entry到此位置,但是如果此位置上已经有元素则会用equals比较,如果也相同则会更新value值。
于是乎我就考虑到这里如果一个类中重写equals和hashcode函数使之均返回同样值,那么,是不是放同样对象时候会调用两次hashcode和一次equals呢?
于是乎写了一下实验代码
import java.util.*;
class keys
{
public boolean equals(Object k)
{
System.out.println("enter equals");
return true;
}
public int hashCode()
{
System.out.println("enter hashCode");
return 2;
}
}
public class testHashMap
{
public static void main(String[] args) {
HashMap<keys,Integer> map = new HashMap<keys,Integer>();
keys k = new keys();
map.put(k,1);
map.put(k,1);
System.out.println(">>>>");
System.out.println(map.size()+">>>>"+map.get(k));
}
}
但是这个程序的输出是这样的
enter hashCode
enter hashCode
>>>>
enter hashCode
1>>>>1
这个结果我十分不解,为什么没有调用equals 呢?
于是将main中代码调换成如下<pre name="code" class="java">public static void main(String[] args) {
HashMap<keys,Integer> map = new HashMap<keys,Integer>();
keys k = new keys();
map.put(k,1);
map.put(new keys(),1);
System.out.println(">>>>");
System.out.println(map.size()+">>>>"+map.get(k));
}
这样子的输出结果是这样的
enter hashCode
enter hashCode
enter equals
>>>>
enter hashCode
1>>>>1
为什么这次就有输出了呢????带着疑问去查看了一下源码。
源码中是这么写的
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && <span style="color:#ff0000;">((k = e.key) == key || key.equals(k)</span>)) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
于是乎问题就得到了解释,如果在hash相同的情况下,并且(k=e.key)==key为true时,是不会调用equals的,这也就合理的解释了为啥在同一个对象时木有调用equals,
而不同对象需要调用equals了。