散列是什么?
散列又称为hash,设K为key,那么则有存储位置下标 index = F(k).这里F做的事情
也就是我们本文要讲的散列,hash。通过散列算法。我们避免了循环比对,实现了不规
则数据高效率存取
Java HashMap 数组+链表
什么是hash碰撞
如上图,数组+链表,将我们的每一个KV的映射关系保存到了对象数组中。那么有:
PUT = F(K) = 构造entry对象 = insert entry array
GET = F(k) = 查找entry对象 = find single entry
看似完美,但是,key不相同,经过hash之后,下标位置不唯一有下列情况
index=F(KEY1)=F(KEY2)=F(KEY3)
我们的数组下标一个位置只能保存一个entry对象。但是现在KEY1,KEY2,KEY3全部
映射到了一个下标位置上。这就叫做hash碰撞
解决Hash碰撞
如上所述,hash算法其实没有完美的一对一的高效计算方式,它还是可能计算到相
同的数组下标位置,造成没有位置存储的尴尬,那么遇到这种情况,我们应该怎么办呢?
1-高效的算法(取模素数)
2-灵活的存储(next insert)
最大质数算法
为了减少hash冲撞,最大质数取模的算法只是其中一种,本篇,我们针对此算法做讨论
假设有一个数组容量为16.最大质数为13.那么
index=k.hashcode mod 13 = F(k)
问题:为什么用最大质数作为取模对象呢?
质数:又叫素数,定义为只能被1和它本身整除的数。
设数组容量size为Y,Y下面最大的素数为X,则Y>X
在KHC = k.hashcode不规则的情况下,有khc mod X = Z
那么Z只有在KHC = X本身 或 KHC = 1 或 KHC = X的倍数三种情况的时候Z才为0
如果X更换为非素数,那么,Z为0的次数变多了(可整除的次数增多),余数重复次数增
多,导致碰撞几率变大。
为什么是最大的质数?
设Y为16,那么16下的质数为1 3 5 7 11 13几个。
我们都知道余数<除数,也就是 Z<X.
那么 如果 X = 3 那么Z下标只有 0 1 2 三个位置可用。
而X = 5的时候, Z的取值范围为 0-4 五个位置可用。
由此可以推出,当取模用最大的质数的时候,导致余数为0的概率是最低的,也就是
hash冲突最小的时候.
PUT和GET 碰撞存取
entry的存储结构
hash put
HASH得到下标,如果下标内有entry对象,则取得entry.next 直到为null,则
放入entry对象,最后一个entry的next对象指向我们put对象,我们put进去的对象
next指向null
hash get
hash 获取entry。比对entry的key和当前传入的key,如果相同则return,不同则
next再次比对,直到相同return..
声明:
以上内容是笔者目前理解到的部分,仅用以交流,如有问题,欢迎指出,本篇未完待
续..