posts - 28,  comments - 15,  trackbacks - 0
    使用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 阅读(416) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 
<2012年8月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(1)

随笔分类(17)

随笔档案(28)

文章分类(30)

文章档案(30)

相册

收藏夹(2)

hibernate

java基础

mysql

xml

关注

压力测试

算法

最新随笔

搜索

  •  

积分与排名

  • 积分 - 95630
  • 排名 - 603

最新评论

阅读排行榜

评论排行榜