经常会被问到的hashcode冲突问题

面试时,有时会被问到HashMap是如何解决hashcode冲突的。

主要使用 “拉链法”

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;  
            //判断当前确定的索引位置是否存在相同hashcode和相同key的元素,如果存在相同的hashcode和相同的key的元素,那么新值覆盖原来的旧值,并返回旧值。  
            //如果存在相同的hashcode,那么他们确定的索引位置就相同,这时判断他们的key是否相同,如果不相同,这时就是产生了hash冲突。  
            //Hash冲突后,那么HashMap的单个bucket里存储的不是一个 Entry,而是一个 Entry 链。  
            //系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的 Entry 位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),  
            //那系统必须循环到最后才能找到该元素。  
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
                V oldValue = e.value;  
                e.value = value;  
                return oldValue;  
            }  
        }  
        modCount++;  
        addEntry(hash, key, value, i);  
        return null;  
    }  

如图所示

例如:A、B、C ,A计算出来的索引为0,此时存储为table[0],此时B计算出来的也是0,那么就会存储为B.entry=A,table[0]=B,此时C也为0,那么就会存储为C.entry = B,table[0]=C,这样就会把A、B、C都存储进去。

 

 具体说下是如何比较的(显示比较hashcode,如何hashcode相等,再去比较equals方法)

 

写一个测试类

class A {  
  
    @Override  
    public boolean equals(Object obj) {  
        System.out.println("判断equals");  
        return false;  
    }  
  
    @Override  
    public int hashCode() {  
        System.out.println("判断hashcode");  
        return 1;  
    }  
}  
public class Test {    
    
    public static void main(String[] args) {    
        Map<A,Object> map = new HashMap<A, Object>();    
        map.put(new A(), new Object());    
        map.put(new A(), new Object());    
            
        System.out.println(map.size());    
    }    
        
}   

输出结果

判断hashcode 
判断hashcode 
判断equals 

说明:因为第一个map中是没有hashcode值的,所以只比较了hashcode,而第二次,map中存在相同的hashcode值,所以去比较对象,对象返回的是false,所以永远不会相同,这样就存储进去了。

如果将equals改为true,

class A {  
  
    @Override  
    public boolean equals(Object obj) {  
        System.out.println("判断equals");  
        return true;  
    }  
  
    @Override  
    public int hashCode() {  
        System.out.println("判断hashcode");  
        return 1;  
    }  
}  

此时再去执行,就会是

判断hashcode 
判断hashcode 
判断equals 

也验证了如下结果:

1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。 
2、如果两个对象不equals,他们的hashcode有可能相等。 
3、如果两个对象hashcode相等,他们不一定equals。 
4、如果两个对象hashcode不相等,他们一定不equals。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值