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 && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 
这个判断条件怎么看e.hash == hash 都是多余的
==判断出来的不是地址相同吗?地址相同了 hash还会不同么?
不能改写成
if (((k = e.key) == key || key.equals(k))) 或者直接 if(key.equals(k)) 我觉得也能够判断了
不过JDK里面那么写自然有它的道理,但我体会不出,
谁能详细讲解一下啊!

解决方案 »

  1.   

    因为equals方法可能非常慢。而先比较一下hash会提高效率
      

  2.   

    但连接的不是|| 操作符吗 equals方法最后都要执行的
    就算hash不同。
      

  3.   


    里是指前面hash相等后(前面个表达式) equals方法不执行所带来的效率提升
    但为什么不能直接用
    ((k = e.key) == key 
    来代替e.hash == hash && ((k = e.key) == key 
    也是效率问题?
      

  4.   

    hash是int类型的,==判断的是hash值不是地址
      

  5.   

    我困惑的是
    ((k = e.key) == key
    这个表达式
    明明比较了地址 还要hash干嘛
      

  6.   

    hash是int类型的,==判断的是hash值不是地址
      

  7.   

    hashCode()方法可以重写,有可能不同的东西经过一个算法后结果一样,所以光有hash的判断还不够,还需要具体的地址比较。
    因为hash是int比较,所以先用hash判断一次比直接上来就判断会快一些
      

  8.   

    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 的意思其实可以看成是if(e.hash == hash) {
       if((k = e.key) == key || key.equals(k)) {
         ...
       }
    }
    这样可以提高比较的速度,只要hash不等,则根本不需要进入比较方法((k = e.key) == key 这个是为了当使用同一个key对象时,直接比较而无需进入equals方法
    总体的说,这段代码都是为了提高效率做的。功能上与key.equals(e.key)没有区别,只是效率提高了
      

  9.   

    在这里,hash不等,一定意味着不相同而((k = e.key) == key 这个只是避免了同一个key对象的情况,而没有避免不同hash的情况
    例如put("1", ...);    之后调用get("2")因为"1"与"2"的hash不同,所以根本不会进入后面的比较逻辑
      

  10.   

    因为e.key涉及了寻址取址操作(e本身是个地址,key本身是e的属性)
    所以用hash在前面短路一下可以避免这些操作
      

  11.   

    根本不是寻址问题,只是因为e.key == key只是非常少的特例。更多的情况下是e.hash != hash,所以它们更不可能相等
      

  12.   

    其实key.equals(k) 就可以了。不过一般调用这个方法效率会受影响。
    所以前两个都是为了进行, equals 的 快速判断。e.key=key,肯定 key.queuals(k)。(这个不用讲了吧)e.hash != hash(这个可以理解为 e.key.hashCode() != key.hashCode(),所以 !key.queuals(k))