对于发生Hash冲突的key,如何找到对应value?

来源:互联网 发布:网络层有哪些协议 编辑:程序博客网 时间:2024/05/18 20:12

首先,还是来炒一炒剩饭,毕竟不仅是解惑,更是当作学习笔记来记的!

为什么常见的Hash集合,例如HashSet、LinkedHashSet、HashMap、LinkedHashMap等有如此高的查找能力(后面有时间也会总结一个常见集合的优劣)?

因为它通过一个(或一系列)函数,传递一个key参数,返回一个地址,通过地址直接找到对应value值,你说这样快不快?

Hash表(Hash Table、哈希表、散列表)就是基于此建立的。于是就出现一个情况了,当key1 != key2 ,f(key1)==f(key2),怎么找到key1、key2对应的value呢?

老司机要开车了!!!(理论部分)

以上情况,叫做哈希冲突,这种由同义词引起的冲突,又叫做同义词冲突注意伏笔)。

于是,我们就考虑了,是不是这个f()函数不行啊?

从函数的角度,我们就开发超级函数,使得任意f(keyi)!=f(keyj),就有了直接定址法,即 f(k)=k+c,这就不可能有冲突了,但是这样k+c<m(地址空间),造成大量内存单元浪费。再想,除留余数法f(k)=k mod p(p=<m(地址空间)),研究表明,p取小于m的素数(质数)最佳,但是仍然会发生冲突。当然还有数字分析法平方取中法折叠法等,就不一一说了,都有可能发生哈希冲突,就得换个思路了,怎么解决冲突?

从解决冲突的角度,主要有开放定址法拉链法。

开放地址法:又分线性探查法平方探查法。

线性探查法:遇到冲突查找下一个非空地址,存入。于是就出现f(key1)==f(key2)+n的冲突了,冤不冤?你先来就能占我位置了? 坚决抵制!!

平方探查法:遇到冲突,查找非空地址,我不下一个查找,我f(key)+1^2 、f(key)-1^2  、f(key)+2^2  、f(key)-2^2,你以为这样就不耍流氓了??抵制!!!

于是拯救世界的拉链法出现了!英雄总是最后出场的!!

咱们同义词冲突嘛,f(key1)=f(key2)=f(key3)=....,咱们都是好兄弟,咱们的f(key)这里不放value,咱们放一个地址,一个链表的指针,再有兄弟来,往链表后面加value,大家和谐共处!

于是,我的问题终于到了,key1 的value1,key2的value2都在这条链表上,那我通过getValue(K key)怎么找到我的value呢???

爪洼大法好!打波广告不要介意!

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        int hash;...}

看到木有??有Key,有Value,还有hash(=f(Key))。getValue(K key)嘛,先来f(key)找到咱们链表,你以为链表就存value?too young to simple!要来取value吧,找对了位置还要有身份证(key)。。

个人理解,若有勘误,敬请指出!

0 0