HashMap源碼之其餘

/**
* 計算hash方法
* 這裏之因此沒有直接使用key的hash.是爲了應對當key的hash分佈很是差的時候,會間接致使
* hash桶的分佈很是差,從而影響性能.因此使用原hash異或(XOR)原hash的高16位,做爲實際使用的hash
* 這裏之因此使用16:16,而不是8:8:8:8或其餘值,是由於jdk開發者充分考慮了時間,效率,性能等各方面
* 的狀況後的折中選擇.
* 同時也是由於當前jdk大多數的hash已經有了較好的分佈,因此也不須要進行過多的處理
* 計算過程以下
* 10000000000000000000000000000000
* 00000000000000001000000000000000
* 10000000000000001000000000000000
*/
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

/**
 * 當對象x(key)存在如class C implements Comparable<C>的實現時,返回x的類型
 * 這裏主要驗證了Comparable<C>部分,防止在後續比較中調用Comparable.compareTo(T t)方法調用失敗
 */
static Class<?> comparableClassFor(Object x) {
    if (x instanceof Comparable) {
        Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
        if ((c = x.getClass()) == String.class) // bypass checks
            return c;
        if ((ts = c.getGenericInterfaces()) != null) {
            for (int i = 0; i < ts.length; ++i) {
                if (((t = ts[i]) instanceof ParameterizedType) &&
                    ((p = (ParameterizedType)t).getRawType() ==
                     Comparable.class) &&
                    (as = p.getActualTypeArguments()) != null &&
                    as.length == 1 && as[0] == c) // type arg is c
                    return c;
            }
        }
    }
    return null;
}

/**Comparable
* 在comparableClassFor方法後調用,已經肯定k實現了Comparable接口
* kc是k的類型(多是一個實現了Comparable的類型)
* 若是x的類型與k的類型不相等,返回0.不然返回compare的結果
* 注: 這裏有一個特別的地方,就是x.getClass() != kc部分.當節點的各鍵類型不一樣時,即
* 使他們k實現了Comparable接口,也不會調用
*/
static int compareComparables(Class<?> kc, Object k, Object x) {
    return (x == null || x.getClass() != kc ? 0 :
            ((Comparable)k).compareTo(x));
}

/**
 * 計算一個大於輸入值的最小的2次冪.
 * 直接上流程(暫時忽略cap - 1部分,最後說)
 * 10000    16  n初始狀態
 * 11000    24  n|=n>>>1 等價於 n = 10000|01000 = 11000
 * 11110    30  n|=n>>>2 等價於 n = 11000|00110 = 11110
 * 11111    31  n|=n>>>4 等價於 n = 11110|00001 = 11111
 * 11111    31  略
 * 11111    31  略
 * 100000   32  n+1
 * 最後,經過+1,將...111變爲100...,即2的n次冪
 * 
 * 這裏使用了一個頗有意思的方式完成了工做,就是輸入值的最高有效位.
 * 經過不斷的向低位複製最高有效位(1),將全部低位換爲1,最終這個值等於(2^n)-1.同時
 * 也是當前數字的最高位能表達的最大值
 * 那麼,再對這個值+1就可使這個值變成2^n.也就是大於輸入值的最小的2的冪
 * 
 * cap - 1的做用:
 * 若是輸入值已是2的冪,那麼這個方法應該直接返回他.直接進行-1,使用原邏輯便可
 * 
 */
static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
相關文章
相關標籤/搜索