使用java的人都知道,如果覆盖了Object的equals方法,那么必须要覆盖hashCode方法,并且如果两个对象用equals方法比较返回true,那么这两个对象hashCode返回的值也必须是相等的,并且对于同一个对象,equals方法需要比较的属性值没有被修改,那么每次调用hashCode返回的值应该是一致的。
那么为什么需要这样呢,是不是所有的对象在覆盖Object的equal方法时都需要覆盖hashCode方法呢?下面以一个实例来说明该问题:
public class HashTest
{
@Test
public void testEqualAndHash()
{
Map<HashObject, String> map = new HashMap<HashObject, String>();
for(int i = 0; i < 10; i++)
{
HashObject o = new HashObject();
o.setId(i);
o.setIdCard("id_" + i);
o.setName("name_" + i);
o.setAddress("address_" + i);
map.put(o, o.getName());
System.out.println();
}
HashObject o = new HashObject();
o.setId(0);
o.setIdCard("id_" + 0);
o.setName("name_" + "zhangsan");
String v = map.put(o, o.getName());
/**//* 未实现hashcode方法,调用map的put方法将不会返回旧值,而是返回null */
System.out.println("v:" + v);
System.out.println("size:" + map.size());
}
}
public class HashObject
{
private Integer id;
private String name;
private String idCard;
private String address;
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getIdCard()
{
return idCard;
}
public void setIdCard(String idCard)
{
this.idCard = idCard;
}
public String getAddress()
{
return address;
}
Object o = null;
public void setAddress(String address)
{
this.address = address;
}
public boolean equals(Object o)
{
if(this == o)
return true;
HashObject x = (HashObject) o;
if(x.getIdCard().equals(this.idCard))
return true;
return false;
}
// public int hashCode()
// {
//
// return 17 * 37 + this.idCard.hashCode();
//
// }
} 关闭与开启HashObject的hashCode方法的执行结果
v:null
size:11
----------------------
v:name_0
size:10
那么为什么会这样呢,让我们看看
1public V put(K key, V value) {
2 if (key == null)
3 return putForNullKey(value);
4 /**//*对key的hashcode做hash运算*/
5 int hash = hash(key.hashCode());
6 /**//*获得key对应的Entry的索引位置*/
7 int i = indexFor(hash, table.length);
8 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
9 Object k;
10 /**//*HashMap采用链表来解决hashcode冲突,从这里可以看出,只有hashcode相等,且equals或者地址相等,HashMap才认为对象是相同的*/
11 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
12 V oldValue = e.value;
13 e.value = value;
14 e.recordAccess(this);
15 return oldValue;
16 }
17 }
18
19 modCount++;
20 addEntry(hash, key, value, i);
21 return null;
22 } HashMap的实现就一目了然了。HashMap采用Entry数组作为存储<key,value>的数据结构,数组的索引是同过对key的hashcode做hash运算获得的,HashMap采用链表来解决hash冲突问题。下面让我们看看HashMap的put方法实现:
posted on 2012-08-16 18:39
zhangxl 阅读(415)
评论(0) 编辑 收藏