扰动函数和拉链法模拟HashMap的存储结构
HashMap是Map接口下面的子孙,它对外是K,V结构存储的,而内部也着自己的存储结构,它的get操作是O(1)的时间复杂度,可以说是非常快的找到目录,而添加时,也是O(1),所以在键值存储里,它成为了我们的首选,在多线程情况下,要注意,它不是线程安全的。如果是多线程情况下,请使用ConcurrentHashMap.
就是JDK1.8之前
JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过(n - 1) & hash判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。
我们简单起见,我们使用Map来模块Map的查找方式,真正的Map是使用数组+链表实现的。
使用数组+链表模拟Map
/**
* 原版-扰动法+拉链法
*
* @param list
* @param val
*/
void moniLinkList(LinkedList[] list, String val) {
int length = list.length;
int index = (length - 1) & val.hashCode();
LinkedList linkedList = list[index];
if (linkedList != null) {
linkedList.add(val);
} else {
linkedList = new LinkedList();
linkedList.add(val);
}
list[index] = linkedList;
}
测试一下
@Test
public void moniLinkListTest() {
LinkedList[] list = new LinkedList[8];
moniLinkList(list, "a");
moniLinkList(list, "b");
moniLinkList(list, "c");
moniLinkList(list, "d");
moniLinkList(list, "e");
moniLinkList(list, "f");
moniLinkList(list, "zzl");
for (int i = 0; i < list.length; i++) {
System.out.print(list[i] + " ");
}
}
结到我们希望的结果
null [a] [b] [c] [d, zzl] [e] [f] null
模拟你的Map的查找过程
/**
* 扰动法+拉链法.
*/
void moniMap(Map<Integer, Map<String, String>> moni, String val, int length) {
int index = (length - 1) & val.hashCode();
if (moni.containsKey(index)) {
Map<String, String> map = moni.get(index);
map.put(val, val);
} else {
moni.put(index, new HashMap<String, String>() {{
put(val, val);
}});
}
}
添加一个测试代码
@Test
public void moniTest() {
int len = 4;
Map<Integer, Map<String, String>> moni = new HashMap<>();
moniMap(moni, "a", len);
moniMap(moni, "b", len);
moniMap(moni, "c", len);
moniMap(moni, "b", len);
moniMap(moni, "e", len);
moniMap(moni, "zzl", len);
moniMap(moni, "zhl", len);
moniMap(moni, "zhz", len);
System.out.println(moni);
}
结果
{
0={zzl=zzl, zhz=zhz},
1={a=a, e=e},
2={b=b, zhl=zhl},
3={c=c}
}
从结果中我们可以看到,首先根据扰动法找到一个索引号,然后当不同hash在计算后生成了相同的索引号,这时需要走拉链法,将他们分组到一个链表里,就这样,我们看到
了一个被分组之后的数据。
扰动函数和拉链法模拟HashMap的存储结构的更多相关文章
- 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响
不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 ...
- HashMap的存储结构及原理
1.HashMap的数据结构(HashMap通过hashcode对其内容进行高速查找,是无序的) 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 :数组的存储区是连续的,占 ...
- 拉链法解决Hash节点冲突问题
<?php /* * hash::拉链法解决hash节点存储冲突问题 * ::2014-07-02 * ::Small_Kind */ class small_hash { private $s ...
- 【Java集合学习】HashMap源码之“拉链法”散列冲突的解决
1.HashMap的概念 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io ...
- 链地址法实现HashMap
前注:本文介绍的HashMap并非Java类库的实现.而是根据哈希表知识的一个实现. 上文介绍了开放地址法实现HashTable,它的缺点是对hashCode映射为地址后如果出现重复地址,则会占用其他 ...
- HashMap的存储原理
HashMap是java中相当重要的数据结构,使用HashMap的场景非常之多,因此,了解HashMap实现的过程和原理,是非常有必要的,在一些面试中也会经常被问到.好了,我们赶紧来研究java内部是 ...
- 散列表(拉链法与线性探测法)Java实现
package practice; import java.security.Principal; import java.util.Scanner; import edu.princeton.cs. ...
- HASH表的实现(拉链法)
本文的一些基本概念参考了一部分百度百科,当然只保留了最有价值的部分,代码部分完全是自己实现! 简介 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据 ...
- 拉链法解决hashtable冲突问题
拉链法解决冲突.拉链法解决冲突的做法是将所有的相同Hash值的key放在一个链表中,比如key3和key14在hash之后都是0,那么在数组的键为0的地方存储这两个值,形式是链表.如果不能理解我的文字 ...
随机推荐
- PAT (Basic Level) Practise (中文)-1038. 统计同成绩学生(20)
PAT (Basic Level) Practise (中文)-1038. 统计同成绩学生(20) http://www.patest.cn/contests/pat-b-practise/10 ...
- 746. Min Cost Climbing Stairs@python
On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed). Once you pay ...
- Windows平台下使用vs code搭建python3环境(1)
前言:最近几周在使用python开发的过程中,碰到了好多坑,由于以前使用visual studio 2015习惯了,导致刚开始搭建python开发环境以及管理各种包的时候有点不习惯,再加上python ...
- (2)zabbix硬件需求
1. 硬件需求 无非就是cpu.内存.硬盘之类的1.1 CPU由你的zabbix数据库使用情况来做决定,如果你监控的项目越多,那你的cpu要越好.具体多好,下面有个表格 1.2 内存与硬盘最基本的需求 ...
- 【php】 自带的过滤机制
<?php print_r(filter_list()); ?> 输出类似: Array ( [0] => int [1] => boolean [2] => float ...
- day12-图
- 对linux中source,fork,exec的理解以及case的 使用
fork 使用 fork 方式运行 script 时, 就是让 shell(parent process) 产生一个 child process 去执行该 script, 当 child proc ...
- JAVA面向过程VS面向对象
面向过程 面向过程是一种自顶向下的编程,强调行为过程,可扩展性可维护性差. 优点: 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源. 单片机.嵌入式开发.Linux/Unix等一般 ...
- 解决php7.3 configure: error: off_t undefined
//解决该问题:php7.3 configure: error: off_t undefined; check your library configuration # 添加搜索路径到配置文件echo ...
- 【14】javascript有哪几种数据类型
javascript有哪几种数据类型 六种基本数据类型 undefined null string boolean number symbol(ES6) 一种引用类型 Object **