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语句效率高,但是身为小白的我并没有在代码中看出有什么不同.去度娘找了半个小 ...
随机推荐
- 调用windows系统下的cmd命令窗口处理文件
从后缀名为grib2的文件中查询相关的信息,并将查出来的信息保存起来. 主要是学习java中调用windows下的cmd平台,并进行执行相关的命令. package com.wis.wgrib2; i ...
- Java 一行代码 数组遍历输出
Arrays.stream(arr).forEach(num -> System.out.println(num));
- 什么是java的深浅拷贝?
什么是java的深浅拷贝? 浅拷贝 就是很肤浅的拷贝,只拷贝了别人的地址.没有拷贝地址里面的值.地址里面的值改变后,就都改变了. 深拷贝 就是很深入的拷贝,深入到核心的拷贝,拷贝了别人地址里面的值,别 ...
- 网站开发学习Python实现-Django项目部署-介绍(6.2.1)
@ 目录 1.第一步:找源码 2.第二步:在windows中更改代码 2.第三步:同步到linux中 3.第三步:部署 4.第四步:运行 关于作者 1.第一步:找源码 从github上找一个djang ...
- 关于AES-CBC模式字节翻转攻击(python3)
# coding:utf-8 from Crypto.Cipher import AES import base64 def encrypt(iv, plaintext): if len(plaint ...
- 阿里云Centos7.6中部署nginx1.16+uwsgi2.0.18+Django2.0.4
当你购买了阿里云的ecs,涉及ecs的有两个密码,一定要搞清楚,一个密码是远程链接密码,也就是通过浏览器连接服务器的密码,另外一个是实例密码,这个密码就是ecs的root密码,一般情况下,我们经常用到 ...
- html怎么在网页标题栏上添加图标
需要先把图片格式转换为.ico类型在这个网址在线转换很方便:https://www.easyicon.net/covert/在<head></head>加一行来显示图标(注意, ...
- Java“微服务”还能这么玩!
"微服务"加个引号是因为这不是传统定义的微服务架构,顶多算是"小服务"架构,因为服务实例由集群节点统一加载,非独立部署.下面以图说明一下服务调用流程. 一. ...
- Redis 设计与实现:Redis 对象
本文的分析都是基于 Redis 6.0 版本源码 redis 6.0 源码:https://github.com/redis/redis/tree/6.0 在 Redis 中,有五大数据类型,都统一封 ...
- Spring Cloud 各个组件角色简介
概述 SpringCloud 是一个全家桶式的技术栈,包含了很多组件:包含 Eureka.Ribbon.Feign.Zuul .Hystrix等.每个组件完成对应的功能 组件介绍 - 服务发现 Eur ...