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语句效率高,但是身为小白的我并没有在代码中看出有什么不同.去度娘找了半个小 ...
随机推荐
- C++异常之三 异常处理接口声明
异常处理接口声明 1 一般为了方便程序员阅读代码,提高程序的可读性,会将函数中的异常类型声明至函数头后方,不用一行一行的找抛出内容: 2 这里要注意一点,这属于C++的标准语法,但在VS中这个操作不被 ...
- unity入门—资源导入与场景创建
前言: 从这一篇章开始,我将会通过游戏实例来讲解如何使用unity制作一个标准的游戏,介绍的内容较多,需要整理的东西也多可能中途会有一两天的咕咕咕,预计想要完成两个游戏,一个射击类一个塔防类,从射击类 ...
- JavaScript中遍历的几种方法
1.while循环 while后面跟循环条件和执行语句,只要满足条件,就会一直执行里面的执行 var i = 0 while(){ console.log(i) i++ } 2.do...while循 ...
- Validated 注解完成 Spring Boot 参数校验
1. @Valid 和 @Validated @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法.构造方法.方法参数.方法返回.成员变量上,表示它们需要进行约束校验. ...
- HBase过滤器:SingleColumnValueFilter和FirstKeyOnlyFilter一起使用的问题
FirstKeyOnlyFilter是对第一列进行过滤,hbase中的列按照字典序排列,所以如果SingleColumnValueFilter中的过滤列不是第一列的话,FirstKeyOnlyFilt ...
- js上 三、数据类型
3.1.什么是数据类型 a. 什么是数据类型? 想从生活中出发: 考验智商的时刻到了: 1(只)+1(只)=1(双) 3(天)+4(天)=1(周) 5(月)+7(月)=1(年) 4(时)+9(时)=1 ...
- Web常用编码以及攻击绕过笔记
一.URL编码形式:"%"加上ASCII码(先将字符转换为两位ASCII码,再转为16进制),其中加号"+"在URL编码中和"%20"表示一 ...
- Ecshop V2.7代码执行漏洞分析
0x01 此漏洞形成是由于未对Referer的值进行过滤,首先导致SQL注入,其次导致任意代码执行. 0x02 payload: 554fcae493e564ee0dc75bdf2ebf94caads ...
- Sentinel入门学习记录
最近公司里面在进行微服务开发,因为有使用到限流降级,所以去调研学习了一下Sentinel,在这里做一个记录. Sentinel官方文档:https://github.com/alibaba/Senti ...
- Android插件换肤 一.实现原理
学习缺的不是时间,而是耐心 目的 1.搞懂系统获取资源文件到在加载布局的整个流程是自己实现换肤功能的理论基础 2.提高分析源码.追踪源码的能力 要点 1.XmlResourceParser (通过这个 ...