众所周知,HashMap内部是由一个HashCode的数组和链表组成(jdk1.8后,当链表长度达到一定的阈值后,会将链表转换成红黑树)
在初始化一个HashMap时,默认的的HashCode数组的长度是16,为什么不可以是5,10,13这样的其他数呢?
public V put(K key, V value) { if (key == null) return putForNullKey(value); //计算key的hashcode int hash = hash(key.hashCode()); //计算hashcode在数组里的位置 int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
//用key的hashcode 按位与 上数组长度 static int indexFor(int h, int length) { // 任意一个数 & 15 return h & (length-1); }
void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); if (size++ >= threshold) // 数组长度的2倍 resize(2 * table.length); }
扫描二维码关注公众号,回复:
4811808 查看本文章
redis中有16384个slot,分配的算法和HashMap计算数组下标的算法也是一样的,有兴趣的可以看一下redis的源码~
/* 0x3FFF = 16383 ,也就是16384-1,与hashmap的hash算法不同,redis中用的是crc16算法,但不管怎样,最后也是按位与length-1,取值范围也一定是0-16383 */ return crc16(key,keylen) & 0x3FFF;
还有例如Hadoop中MapReduce时计算数据的分区,kafka中计算存储的分区时,用的是取余的算法.
例如,分区总数是3, 那么任何一个正整数对3取余,结果一定是0 1 2