5. HashMap如何降低Hash冲突概率( 二 )


5. 如何降低Hash冲突概率
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}((p = tab[i = (n - 1) & hash])
1、保证不会发生数组越界
首先我们要知道的是,在,数组的长度按规定一定是2的幂 。因此,数组的长度的二进制形式是:10000…000, 1后面有偶数个0 。那么, - 1 的二进制形式就是01111.111, 0后面有偶数个1 。最高位是0, 和hash值相“与”,结果值一定不会比数组的长度值大,因此也就不会发生数组越界 。一个哈希值是8,二进制是1000,一个哈希值是9,二进制是1001 。和1111“与”运算后,结果分别是1000和1001,它们被分配在了数组的不同位置,这样,哈希的分布非常均匀 。
6. 源码解读 6.1 的作用
我们知道 java.util. 不是线程安全的,因此如果在使用迭代器的过程中有其他线程修改了map,那么将抛出,这就是所谓fail-fast策略 。这一策略在源码中的实现是通过域, 顾名思义就是修改次数,对 内容的修改都将增加这个值,那么在迭代器初始化过程中会将这个值赋给迭代器的。在迭代过程中,判断跟是否相等,如果不相等就表示已经有其他线程修改了 Map:
6.2 扩容产生死循环问题
void transfer(Entry[] newTable, boolean rehash) {int newCapacity = newTable.length;for (Entry e : table) {while(null != e) {Entry next = e.next;if (rehash) {e.hash = null == e.key ? 0 : hash(e.key);}int i = indexFor(e.hash, newCapacity);e.next = newTable[i];newTable[i] = e;e = next;}}}
6.3 扩容底层原理
将原来的链表拆分两个链表存放; 低位还是存放原来index位置 高位存放index=j+原来长度
if ((e.hash & ) == 0) { 由于原来的容量没有减去1 所以所有的hash&
为0或者1;
6.4 加载因子为什么是0.75而不是1或者0.5
产生背景:减少Hash冲突index的概率;
查询效率与空间问题;
简单推断的情况下,提前做扩容:
如果加载因子越大,空间利用率比较高,有可能冲突概率越大;如果加载因子越小,有可能冲突概率比较小,空间利用率不高;
空间和时间上平衡点:0.75
统计学概率:泊松分布是统计学和概率学常见的离散概率分布 6.5 如何存放1万条key效率最高
参考阿里巴巴官方手册:
6.6 为什么JDK官方不承认Jdk7扩容死循环Bug问题
7. 源码解读 7.1 JDK1.源码解读
使用传统保证线程问题,是采用锁将整个中的数组锁住,
在多个线程中只允许一个线程访问Put或者Get,效率非常低,但是能够保证线程安全问题 。
Jdk官方不推荐在多线程的情况下使用或者,建议使用分段 。
效率非常高 。
将一个大的集合拆分成n多个不同的小的(),默认的情况下是分成16个不同的
。每个中都有自己独立的[] table;

5. HashMap如何降低Hash冲突概率

文章插图
7.1.1 简单实现
public class MyConcurrentHashMap {private Hashtable[] segments;public MyConcurrentHashMap() {segments = new Hashtable[16];}public void put(K k, V v) {int segmentIndex = k.hashCode() & segments.length - 1;Hashtable hashtable = segments[segmentIndex];if (hashtable == null) {hashtable = new Hashtable();}hashtable.put(k, v);segments[segmentIndex] = hashtable;}public V get(K k) {int segmentIndex = k.hashCode() & segments.length - 1;Hashtable hashtable = segments[segmentIndex];if (hashtable != null) {return hashtable.get(k);}return null;}public static void main(String[] args) {MyConcurrentHashMap concurrentHashMap = new MyConcurrentHashMap