首先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次方。