HashMap hash方法分析

HashMap 中hash table 定位算法:

Java代码 HashMap hash方法分析 HashMap hash方法分析HashMap hash方法分析
  1. int hash = hash(key.hashCode());   
  2. int i = indexFor(hash, table.length);  
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);


其中indexFor和hash源码如下:

Java代码 HashMap hash方法分析 HashMap hash方法分析HashMap hash方法分析
  1. /**  
  2.  * Applies a supplemental hash function to a given hashCode, which  
  3.  * defends against poor quality hash functions.  This is critical  
  4.  * because HashMap uses power-of-two length hash tables, that  
  5.  * otherwise encounter collisions for hashCodes that do not differ  
  6.  * in lower bits. Note: Null keys always map to hash 0, thus index 0.  
  7.  */  
  8. static int hash(int h) {   
  9.     // This function ensures that hashCodes that differ only by   
  10.     // constant multiples at each bit position have a bounded   
  11.     // number of collisions (approximately 8 at default load factor).   
  12.     h ^= (h >>> 20) ^ (h >>> 12);   
  13.     return h ^ (h >>> 7) ^ (h >>> 4);   
  14. }   
  15.   
  16. /**  
  17.  * Returns index for hash code h.  
  18.  */  
  19. static int indexFor(int h, int length) {   
  20.     return h & (length-1);   
  21. }  
    /**
     * Applies a supplemental hash function to a given hashCode, which
     * defends against poor quality hash functions.  This is critical
     * because HashMap uses power-of-two length hash tables, that
     * otherwise encounter collisions for hashCodes that do not differ
     * in lower bits. Note: Null keys always map to hash 0, thus index 0.
     */
    static int hash(int h) {
        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

    /**
     * Returns index for hash code h.
     */
    static int indexFor(int h, int length) {
        return h & (length-1);
    }


indexFor这个方法论坛中已有人分析过,这里就不再分析。
现在分析一下hash算法:

Java代码 HashMap hash方法分析 HashMap hash方法分析HashMap hash方法分析
  1. h ^= (h >>> 20) ^ (h >>> 12);   
  2. return h ^ (h >>> 7) ^ (h >>> 4);  
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);


假设key.hashCode()的值为:0x7FFFFFFF,table.length为默认值16。
上面算法执行如下:

HashMap hash方法分析

得到i=15

其中h^(h>>>7)^(h>>>4) 结果中的位运行标识是把h>>>7 换成 h>>>8来看。

即最后h^(h>>>8)^(h>>>4) 运算后hashCode值每位数值如下:
8=8
7=7^8
6=6^7^8
5=5^8^7^6
4=4^7^6^5^8
3=3^8^6^5^8^4^7
2=2^7^5^4^7^3^8^6
1=1^6^4^3^8^6^2^7^5
结果中的1、2、3三位出现重复位^运算
3=3^8^6^5^8^4^7     ->   3^6^5^4^7
2=2^7^5^4^7^3^8^6   ->   2^5^4^3^8^6
1=1^6^4^3^8^6^2^7^5 ->   1^4^3^8^2^7^5

算法中是采用(h>>>7)而不是(h>>>8)的算法,应该是考虑1、2、3三位出现重复位^运算的情况。使得最低位上原hashCode的8位都参与了^运算,所以在table.length为默认值16的情况下面,hashCode任意位的变化基本都能反应到最终hash table 定位算法中,这种情况下只有原hashCode第3位高1位变化不会反应到结果中,即:0x7FFFF7FF的i=15。