HashMap为什么效率高?来看看这个小demo
一、前情回顾:在程序中有时候需要存放对象,容器应运而生。容器分为集合和Map。集合在这里不说,说说Map。Map在英语中是地图的意思,这个名字真是起的好,可以让人顾名思义。Map,就是存放键值对的结构。也就是说,只要找到键,就能找到对应的值,就跟查字典一样。
二、Map工作效率的深层原理:
1.上面说到查询map就是查询键,只要键找得到,值就会对应的找得到。所以怎么找到键,就是访问Map的效率的瓶颈所在。
2.那么如何找到键呢?其中一个好办法就是把键排序,然后按照二分法查找。二分法就不用介绍了吧?
3.散列(HashMap)则更进一步。他把键相关的信息保存在一个数组中。因为数组时访问速度最快的数据结构。这样可以大大提高效率。但是数组中存储的是键的相关信息,而不是键本身。因为Map的大小是不确定的,而数组的大小是确定的,所以问题来了,怎么把不确定size的Map的键的相关信息存储在数组中呢?
4.那就是数组并不保存键本身,只保存于键相关的信息,这个相关信息就是每一个键对象生成的数字,将其作为数组的下表,这个数字就是散列码,即hashCode()方法。
5.不同的键可以产生相同的散列码,对应于数组的相同下标。这样就解决了数组大小不变的问题。即:数组中的每一个具体的位置,可以根据Map的大小存储一个或多个Map基本元素,这样就会保证Map可以自由调节大小。Map小了,把数组填不满,Map大了,就往数组的同一个位置多填几个值。其数据结构如下图:

代码如下
package test; import java.util.Map; /**
* @author 笑傲独行侠
* @description:
* @Date: 2019/7/9 13:55
*/
public class MapEntry<K, V> implements Map.Entry<K, V> {
private K key;
private V value; public MapEntry(K key, V value) {
this.key = key;
this.value = value;
} @Override
public K getKey() {
return key;
} @Override
public V getValue() {
return value;
} @Override
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
}
package test; import java.util.*; /**
* @author 笑傲独行侠
* @description: 理解HashMap的深层原理
* @Date: 2019/7/9 11:33
*/
public class SimpleHashMap<K, V> extends AbstractMap<K, V> {
static final int SIZE = 997;//定义数组的大小,尽量大一下,使得一个map尽量存入不同的下标数组中
LinkedList<MapEntry<K, V>>[] buckets = new LinkedList[SIZE];//定义一个数组,存放键的相关信息,数组中是List public V put(K key, V value) {
V oldValue = null;
//先计算key的hashCode值,再处理一下算出对应的数组下标
int index = Math.abs(key.hashCode()) % SIZE; //如果该下标对应的还没有值,就先new一个List
if (buckets[index] == null) {
buckets[index] = new LinkedList<MapEntry<K, V>>();
} //如果该下标已经有一个key存放在其中,就将当前key添加到该List中。
LinkedList<MapEntry<K, V>> bucket = buckets[index];
MapEntry<K, V> pair = new MapEntry<K, V>(key, value);
boolean found = false;
ListIterator<MapEntry<K, V>> it = bucket.listIterator();
while (it.hasNext()) {
MapEntry<K, V> iPair = it.next();
if (iPair.getKey().equals(key)) {
oldValue = iPair.getValue();
it.set(pair);
found = true;
break;
}
}
//定义一个Boolean变量,如果要存入的键已经存在,则替换该键对应的值,如果不存在则添加
if (!found)
buckets[index].add(pair);
return oldValue;
} @Override
public V get(Object key) {
int index = Math.abs(key.hashCode()) % SIZE;
if (buckets[index] == null)
return null;
for (MapEntry<K, V> iPair : buckets[index]) {
if (iPair.getKey().equals(key))
return iPair.getValue();
}
return null;
} @Override
public Set<Entry<K, V>> entrySet() {
Set<Map.Entry<K, V>> set = new HashSet<>();
for (LinkedList<MapEntry<K, V>> bucket : buckets) {
if (bucket == null) {
continue;
}
for (MapEntry<K, V> mPair : bucket) {
set.add(mPair);
}
}
return set;
} public static void main(String[] args) {
SimpleHashMap<String, String> m = new SimpleHashMap<>();
m.put("111", "huhhu");
m.put("111", "huhhu");
m.put("111", "huhhu");
m.put("111", "huhhu");
System.out.println(m);
System.out.println(m.get("ERITREA"));
System.out.println(m.entrySet());
}
}
HashMap为什么效率高?来看看这个小demo的更多相关文章
- 遍历hashMap对效率的影响
测试环境:jdk1.7.0_79\Processor 1.7 GHz Intel Core i5 遍历Map的方式有很多,通常场景下我们需要的是遍历Map中的Key和Value. 写了两个方法: pu ...
- 为什么switch...case语句比if...else执行效率高
在C语言中,教科书告诉我们switch...case...语句比if...else if...else执行效率要高,但这到底是为什么呢?本文尝试从汇编的角度予以分析并揭晓其中的奥秘. 第一步,写一个d ...
- 【OCP、OCM、高可用等】小麦苗课堂网络班招生简章(从入门到专家)--课程大纲
[OCP.OCM.高可用等]小麦苗课堂网络班招生简章(从入门到专家)--课程大纲 小麦苗信息 我的个人信息 网名:小麦苗 QQ:646634621 QQ群:618766405 我的博客:http:// ...
- C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?
还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...
- PHP 比 Java 的开发效率高在哪?
PHP 比 Java 的开发效率高在哪? 现在很多互联网应用都是php开发的,在很多人的观念里已经把php与java分到了两个开发领域,php是互联网,java是企业应用. 都说php的开发效率高,更 ...
- 为什么golang的开发效率高(编译型的强类型语言、工程角度高、在开发上的高效率主要来自于后发优势,编译快、避免趁编译时间找产品妹妹搭讪,既是强类型语言又有gc,只要通过编译,非业务毛病就很少了)
作者:阿猫链接:https://www.zhihu.com/question/21098952/answer/21813840来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- 笨重的mfc还在基于系统控件,熟练的mfc工程师还比不过学习Qt一个月的学生开发效率高(比较精彩,韦易笑)
作者:韦易笑链接:https://www.zhihu.com/question/29636221/answer/45102191来源:知乎著作权归作者所有,转载请联系作者获得授权. 更新:擦,本来只有 ...
- 你还在认为 count(1) 比 count(*) 效率高?
你还在认为 count(1) 比 count(*) 效率高? 3 很多人认为count(1)执行的效率会比count()高,原因是count()会存在全表扫描,而count(1)可以针对一个字段进行查 ...
- 为什么说在使用多条件判断时switch case语句比if语句效率高?
在学习JavaScript中的if控制语句和switch控制语句的时候,提到了使用多条件判断时switch case语句比if语句效率高,但是身为小白的我并没有在代码中看出有什么不同.去度娘找了半个小 ...
随机推荐
- EHCACHE实现登录错误次数账号锁定
使用EHCACHE实现账号密码登录校验失败5次锁定10分钟 <?xml version="1.0" encoding="UTF-8"?> <e ...
- PsySH作为调试器
PsySH作为调试器 PsySH可以用来在脚本中设置一个断点,在这个断点处它将暂停并提供对shell的访问,以检查变量并在断点所在位置的上下文中运行命令.目前它不支持逐步调试(如xdebug),但在需 ...
- 四、testNG.xml 简单介绍
TestNG定义了一套非常具体的术语描述测试. testng.xml testng.xml是一个以XML记录所有测试的文件.可以利用这个文件,跑同一个类或者多个不同类里面的测试用例. testng.x ...
- 【面试专栏】ArrayList 非线程安全案例并提供三种解决方案
1. 复现问题 import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * 复现问题 * * @au ...
- Vue-router hash模式微信登录授权验证,#号处理
微信授权登录验证会把网址中的#号去掉,这样在跳转的时候Vue拿不到Code.所以做了以下处理 let href = window.location.href; if (href.includes(&q ...
- c++日常小问题
语法解析问题. 当给一个变量构造函数传递一个临时变量,而不是命名的变量,c++编译器会将其解析为函数声明,而不是类型对象的定义. class hello { void operator()() { s ...
- js下 Day03、DOM操作--节点方法
语法:parentNode.appendChild(child) 功能:向父节点的子节点列表的末尾添加新的子节点 语法:parentNode.removeChild(child) 功能:从子节点列表中 ...
- 逆袭故事|从“点点点”到月薪17K,这个女孩子做到啦
姓:XXX,XX VIP 学员,一名自动化测试工程师!之前在某大型培训机构转行学习软件测试时就是木子老师的学生,她也一直关注木子老师的动态,后来知道木子老师打算开设测试开发高级提升班,等开了班就报名了 ...
- Erlang那些事儿第1回之我是变量,一次赋值永不改变
第1回先从不变的变量说开来,学过其他编程语言的人都知道,变量之所以叫变量,是因为它会经常变,被修改.假设原本X = 10,后来再执行X = 24,那么X就从10变成了24,这对于程序新手和老鸟来说, ...
- 悉数 Python 函数传参的语法糖
TIOBE排行榜是程序开发语言的流行使用程度的有效指标,对世界范围内开发语言的走势具有重要参考意义.随着数据挖掘.机器学习和人工智能相关概念的风行,Python一举收获2018年年度语言,这也是Pyt ...