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;
}

猜你喜欢

转载自www.cnblogs.com/heaven-elegy/p/11890716.html
今日推荐