neo 的小窝
欢迎来到 neo 的小窝,更多参见我的 GitHub账号 http://github.com/neocxf

为了实现一个通过 Hash 寻址的方式,获得存储的元素,首先要考虑的选择何种 Hash 算法。 HashMap 选择了近似于取模的方式,获得元素存储的位置。当然为了提高性能,且降低key 的碰撞。HashMap主要做了两方面的优化

 

1. 对Hash取值的优化

我们当然可以直接选择存储的 key 的 hashcode() 方法得到 key 的 hash 值。但是对一些hashcode值比较接近的key,可能会造成存储时,分配不均。通常情况下,决定key 分配位置的其实是 key 的hash 值的低位部分。所以,为了

让 hash 值在分配时更加均匀,可以采用如下方法

static final int spread(int h) {
        return (h ^ (h >>> 16)) & 0x7fffffff;
}

 

2. 对数组大小的优化

一般情况下,我们可以直接采用 hash % CAP (CAP为具体存储数组的大小) 得到某个 key 在数组的下标。但这种取模的方式相对性能较低,HashMap 采用了另外一种方式,即将数组的容量设定为 2 的 n 次幂,再使用 与 的形式获得下标。

这里面主要涉及到了如下算法

/**
     * Returns a power of two table size for the given desired capacity.
     * See Hackers Delight, sec 3.2
     */
    private static final int tableSizeFor(int c) {
        int n = c - 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;
    }

进行下标的计算时,我们可以使用如下方式得到:

(spread(key.hashcode() & (table.length-1))  

上述 tableSizeFor 方法的目的是找到比给定 c 最近的 2 的 n 次幂的最小值

 

至于 tableSizeFor  方法的原理,大家可以参考一下这篇文章

 

 

参考资料:

1  HashMap 源码解析

HashMap tableSizeFor

 

posted on 2020-03-25 16:27  neo的小窝  阅读(1644)  评论(0)    收藏  举报