hashMap 容量相关的部分源码解读

首先HashMap有这几个参数

 /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The bin count threshold for using a tree rather than list for a
     * bin.  Bins are converted to trees when adding an element to a
     * bin with at least this many nodes. The value must be greater
     * than 2 and should be at least 8 to mesh with assumptions in
     * tree removal about conversion back to plain bins upon
     * shrinkage.
     */
    static final int TREEIFY_THRESHOLD = 8;

    /**
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
     */
    static final int UNTREEIFY_THRESHOLD = 6;

    /**
     * The smallest table capacity for which bins may be treeified.
     * (Otherwise the table is resized if too many nodes in a bin.)
     * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
     * between resizing and treeification thresholds.
     */
    static final int MIN_TREEIFY_CAPACITY = 64;

1.DEFAULT_INITIAL_CAPACITY=1<<4
这是默认容量16

2.MAXIMUM_CAPACITY = 1 << 30
这是hashMap支持的最大容量 2^30

3.DEFAULT_LOAD_FACTOR=0.75f
这是hashMap的负载因子 hash表中存储的元素达到其长度的75%会自动扩容

4.TREEIFY_THRESHOLD = 8
这是表中链表元素转化为红黑树的阈值

5.UNTREEIFY_THRESHOLD=6
表中红黑树元素退化为链表的阈值

/**
     * Computes key.hashCode() and spreads (XORs) higher bits of hash
     * to lower.  Because the table uses power-of-two masking, sets of
     * hashes that vary only in bits above the current mask will
     * always collide. (Among known examples are sets of Float keys
     * holding consecutive whole numbers in small tables.)  So we
     * apply a transform that spreads the impact of higher bits
     * downward. There is a tradeoff between speed, utility, and
     * quality of bit-spreading. Because many common sets of hashes
     * are already reasonably distributed (so don't benefit from
     * spreading), and because we use trees to handle large sets of
     * collisions in bins, we just XOR some shifted bits in the
     * cheapest possible way to reduce systematic lossage, as well as
     * to incorporate impact of the highest bits that would otherwise
     * never be used in index calculations because of table bounds.
     */
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

这个hash方法是建立在 Object的hashCode方法上
得到hash码后 再和hash码右移16位进行异或得到真正的hash码。其他的方法中例如get,put方法通过(length-1)& hash 运算得到元素的下标(这步运算其实就是求余 要求是length必须是2的n次方)
右移16位的原因是:
如果某个hashMap的容量 在二进制中只占后16位那么计算下标时如下:
上面是hashCode,下面是length-1
0000 0010 1010 0100 0110 0001 0010 0110
&
0000 0000 0000 0000 0000 0000 0000 1111
结果:
0000 0000 0000 0000 0000 0000 0000 0110

问题出在容量的大小一般小于2^16次方
导致高16位不管是多少 ‘&’运算后都是0 导致区分不开容易发生hash碰撞

那么将hashCode
0000 0010 1010 0100 0110 0001 0010 0110
后移16位
0000 0000 0000 0000 0000 0010 1010 0100
再与原hashcode异或
0000 0010 1010 0100 0110 0001 0010 0110
得到最终hashcode
0000 0010 1010 0100 0110 0011 1000 0010
好处是 高16位不变 低16位是原hashCode的高16位和低16位的混合特征码
后面做于运算时hash碰撞的概率会下降。

/**
     * Returns a power of two size for the given target capacity.
     */
    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;
    }

就是将传入的容量传化为2的n次方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值