两个数组

bucket数组:存储key的hash桶,桶指的是把hashcode分配到一定的范围内

entry数组:用来存储实现的值,它是一个单向链表,bucket总是存储链表的最后一个元素

实现方式

通过哈希桶来实现的k/v存储,通过key的hash码,再进行桶计算,生成一个在某个范围内的值,这就是桶的索引号,再把值存储到桶对应的entry里,桶bucket存储了entry的索引号,通过一个bucket可以直接或者间接找到一个entry.

直接找到:当hash没有冲突时,它存储的就是真实的entry索引

间接找到:当hash出现冲突(碰撞)时,它就会把当前最后的索引赋值这个新entry.next,而新的entry的索引就是现在的bucket的值。

实现流程图

graph LR

key-->hashcode

hashcode-->bucket桶运算

bucket桶运算-->得到bucket索引

得到bucket索引-->bucket值就是entry的索引

bucket值就是entry的索引-->x("↓")

graph LR

bucket值就是entry的索引-->冲突解决

冲突解决-->单向链表next指向上一个值

单向链表next指向上一个值-->单身链表查找

单身链表查找-->返回结果

数组长度为素数

hash桶数全部使用的是质数,因为我们在hash的定义中,hash函数使用的是标准的求模函数,因此这样定义桶数有利于元素各个桶之间的均匀分布和减少hash相同值的碰撞概率。

例如:

举一个有点极端的例子,假设我们的元素全是偶数1,4,6,8,10,12,14,1,6,18,20,22

如果我们使用4个桶:

0: 4,8,12,16.20

1:

2:6,10,14,18,22

3:

很明显看出有的桶有很多元素,但是有的桶是空桶,如果我们改为使用3个桶:

0: 6,12,18

1:4,10,16,22

2:2,8,14,20

模拟一个字典的实现

@Getter

@Setter

class KVPair {

private K key;

private T value;

private int hashCode;

private int next; //下一个元素的下标索引,如果没有下一个就为-1

}

/**

* 模拟实现一个字典kv结构.

*

* @param

*/

class MokiHashMap {

static int[] primes = {

3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,

1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,

17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,

187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,

1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};

// 桶数组

private int[] buckets;// 最新的entry的索引号,

// 真实的数据

private KVPair[] entry; // entry根据next形成一个单链表

private int count = 0; // 当前entries的数量

public MokiHashMap() {

buckets = new int[3];

entry = new KVPair[3];

for (int i = 0; i < buckets.length; i++) {

buckets[i] = -1;

}

}

private void reSize() {

int newLength = getPrime(count);

int[] newBuckets = new int[newLength];

for (int i = 0; i < newBuckets.length; i++) {

newBuckets[i] = -1;

}

KVPair[] newEntries = new KVPair[newLength];

System.arraycopy(entry, 0, newEntries, 0, count);

System.arraycopy(buckets, 0, newBuckets, 0, count);

entry = newEntries;

buckets = newBuckets;

}

/**

* 得到某个key所在的hash桶

*

* @param key .

* @return

*/

private int getHashBucketIndex(K key) {

int len = buckets.length;

int hashCode = key.hashCode();

int index = hashCode & (len - 1);//len升级的hash桶

return index;

}

/**

* 得到较大的素数.

*

* @param min .

* @return

*/

private int getPrime(int min) {

if (min < 0) {

throw new IllegalArgumentException("最小为3");

}

for (int i = 0; i < primes.length; i++) {

int prime = primes[i];

if (prime > min) return prime;

}

return min;

}

public void add(K key, T value) {

if (count == entry.length) {

reSize();

}

int index = getHashBucketIndex(key);

int entryIndex = buckets[index];

entry[count] = new KVPair();

if (entryIndex < 0) {

entry[count].setNext(-1);

} else {

entry[count].setNext(buckets[index]);

}

entry[count].setHashCode(index);

entry[count].setKey(key);

entry[count].setValue(value);

buckets[index] = count;

count = count + 1;

}

public T find(K key) {

int entryIndex = buckets[getHashBucketIndex(key)];

while (entry[entryIndex].getNext() > -1) {

if (entry[entryIndex].getKey().equals(key)

&& entry[entryIndex].getHashCode() == getHashBucketIndex(key)) {

return entry[entryIndex].getValue();

}

entryIndex = entry[entryIndex].getNext();

}

return null;

}

}

public class KVTest {

@Test

public void testDic() {

MokiHashMap dic = new MokiHashMap<>();

dic.add("ok", "1");

dic.add("zzl", "2");

dic.add("lr", "3");

dic.add("dd", "1");

dic.add("a", "b");

dic.add("b", "c");

dic.add("d", "e");

dic.add("e", "f");

System.out.println("dic find:" + dic.find("a"));

}

}

内容来源于网络如有侵权请私信删除

字典哈希表的实现原理_字典哈希表的实现原理相关推荐

  1. 小牛485通讯原理_让你秒懂智能电表工作原理及抄表原理

    一.智能电表的工作原理 1.智能电表主要是由电子元器件构成,其工作原理是先通过对用户供电电压和电流的实时采样,再采用专用的电能表集成电路,对采样电压和电流信号进行处理,并转换成与电能成正比的脉冲输出, ...

  2. python对于字典d d.get(x、y)_字典的使用与操作

    python字典是另一种可变容器,可存储任意类型对象,如字符串.数字和元组等容器模型 一.创建字典: 字典由key和value成对组成.字典也被称作关联数组或哈希表.key可以是多种类型,但key是唯 ...

  3. 中间表增加额外字段_如何定制分表中间件

    前言 一般来说,影响数据库最大的性能问题有两个,一个是对数据库的操作,一个是数据库中的数据太大.对于前者我们可以借助缓存来减少一部分读操作,针对一些复杂的报表分析和搜索可以交给 Hadoop 和 El ...

  4. python中字典的输出序列_python3:序列_字典(常用基础知识)

    #字典: '''字典:无序的.可变的序列,也称关联数组,或散列表 ①格式{键:值} ②通过键读取元素 ③字典是任意对象的无序集合 ④字典可任意嵌套,如元素可以为列表.字典.列表的列表等 ⑤字典的键必须 ...

  5. mysql表空间过大_详解MySQL表空间以及ibdata1文件过大问题

    ibdata1文件过大 原因分析 ibdata1是一个用来构建innodb系统表空间的文件,关于系统表空间详细介绍参考MySQL官网文档 上面是一个数据库的ibdata1文件,达到了780多G,而且还 ...

  6. java断点续传原理_很简单的Java断点续传实现原理

    原理解析 在开发当中,"断点续传"这种功能很实用和常见,听上去也是比较有"逼格"的感觉.所以通常我们都有兴趣去研究研究这种功能是如何实现的? 以Java来说,网 ...

  7. jdbc 自增id 原理_给“小白”漫画+图示讲解MyBatis原理,就问香不香!

    MyBatis一款后起之秀的持久层框架ORM,支持自定义SQL.存储过程和高级映射,相对于Hibernate算是半自动化的框架,在国内行业内非常流行. 常规的JDBC操作,配置相应的数据库连接的信息, ...

  8. mysql select内部原理_数据库SQL SELECT查询的工作原理

    作为Web开发人员,虽并非专业的DBA,但我们总是离不开数据库.一般开发员只会应用SQL的四条经典语句:select,insert,delete,update.以至于从来没有研究过它们的工作原理,在这 ...

  9. eja智能压力变送器工作原理_电量变送器是什么?电量变送器工作原理解析

    电量变送器的定义 电量变送器是一种将被测电量(交流电压.电流.有功功率.无功功率.有功电能.无功电能.频率.相位.功率因数.直流电压.电流等)转换成按线性比例直流电流或电压输出(电能脉冲输出)的测量仪 ...

  10. mysql工具分页原理_高效的mysql分页方法及原理

    首先看一下分页的基本原理: 复制代码 代码如下: mysql> explain SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20G * ...

最新文章

  1. sts (eclipse)安装配置lombok
  2. Java 正则表达式的用法与实例
  3. close函数 qt_QT中的close、closeEvent和析构函数的理解(基础知识)
  4. VS连接数据库运行后显示对象名无效
  5. java 计算组合_java – 计算所有可能的组合
  6. 信息系统项目管理师核心考点(七)软件架构风格
  7. c语言浮点数和0比较大小,C-浮点数为什么不能和0比较?
  8. iOS永久签名不掉签工具,轻松签超详使用教程
  9. 中病毒spoolsv.exe
  10. RHEL 5.5 KVM 网卡 bridge设置
  11. 随笔---有关爬虫的总结
  12. 06-jQuery中的防抖和节流
  13. 如何调整图片尺寸大小?电脑怎么修改照片大小?
  14. matlab数字图像处理之局部直方图均衡化
  15. 洛谷P2433 小学数学 N 合一
  16. 中国供应链数字化服务行业图谱
  17. Ubuntu下制作Gif图片
  18. 录制电脑屏幕的软件哪个性价比高?这4款软件就很实用
  19. python编写一个判断完数的函数过程_1.编写一个函数判断一个整数是否是完数(一个数如果恰好等于他的因子之和,这个数就称为完数,如6=1+2+3)...
  20. Express语言和STEP标准

热门文章

  1. 一个完整的接口技术解决方案(一)
  2. 【Spring-tx】AutoProxyRegistrar类
  3. 分布式文件存储FastDFS之安装Nginx实现文件访问
  4. Future机制原理
  5. Nginx配置文档详解
  6. 市场监管总局通报部分转供电主体不执行国家电价政策案例
  7. ARP协议-路由交换原理5-【HCNA笔记】
  8. python+selenium环境配置(windows7环境)
  9. javascript模板插件amaze.js
  10. 【JAVA】什么时候会发生空指针异常