Hashmap
原理
hashmap的底层数据结构散列表,即:数组+链表,创建的时候初始化一个数组,每个节点可以为一个链表
当一键值对发生put操作时,
首先根据key的hash值得到这个元素在数组中的位置(即下标),如果这个位置上已经存在其他元素,将进行下一步操作。
- 由于同一点是链表方式存储,会将原来的元素向后推
- 然后新的元素放在这个位置上
put操作可能会出现冲突,冲突分两种:
- 不同的key值,通过hash函数得出相同的index,这种冲突通过上面所说的链表方式存储。
- 相同的key值,直接覆盖。
所以为了减少冲突,尽量将hashmap 的长度设置为2的次方,因为如果不是2的次方,经过hash & 操作,最后一位总是0如下图,而0001,0011,0101,1001,1011,0111,1101这几个位置永远都不能存放元素了,空间浪费相当大,而且这样可以使用的位置比数组长度小了很多,增加了冲突的几率,故减慢的查询的效率(如果每一个节点都不存在链表,则不需要循环,查询效率会高,所以尽量均匀分布)。
同理,当一键值对发生get操作时,会经过hash函数计算得到index,如果节点为链表有多个元素,则迭代用key.equals()比较获取。
容量
源码多了恶心,少量如下:
static final int DEFAULT_INITIAL_CAPACITY = 16; static final int MAXIMUM_CAPACITY = 1 << 30; static final float DEFAULT_LOAD_FACTOR = 0.75f;
三个常量中可以看出,默认的容器大小是16,最大长度是2的30次方,load factor默认是0.75,扩充的临界值是16*0.75=12,
如果put操作检测出hashmap的容量不足,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元个数能够有效的提高hashmap的性能。
实战总结
所以如果我们想初始化一个容量大小为13的容量,合理的方式是什么呢?
1.Map<String, String> map1 = new HashMap<>(13); 2.Map<String, String> map2 = new HashMap<>(13, 1); 3.Map<String, String> map3 = Maps.newHashMapWithExpectedSize(13);
以上是三种初始化方式
第一种
直接根据构造方法初始化,那么map会初始化一个容量大小为16的map,在超过16*0.75即12的时候发生扩容,这显然不是我们想看到的。
第二种
在构造容量为13的基础上,将负载因子的值设为1,那么map将会在超过16个元素后开发扩容,可以满足我们的预期效果,但这种情况一旦发生扩容,随着元素的增多,碰撞的几率就会升高,链表就会很长,这样就大大的降低了性能。
第三种
使用guava的方式初始化一个map,根据源码发现guava已经帮我算好了,真正需要扩容的临界点,
可以满足我们的期望,同时也不需要修改负载因子的值,所以无特殊情况下,建议使用此方式。
LinkedHashMap
其底层实现基本与hashmap一致,但是linkedHashMap多维护了一张双向的链表
LinkedHashMap成员变量
增加accessOrder属性,默认为false,当为false时,按插入顺序排序,当为true时,
按LRU+插入顺序排序
LRU:最近最少使用算法
Entry
其保存的Entry对象增加了两个属性,before和after
存数据
LinkedHashMap没有重写put方法,而是重写了addEntry()方法,把新的Entry也加到header
链表结构里面去
取数据
1、先调用hashmap的getEntry()方法获取Entry
当accessOrder为true时,把最近使用的当前Entry移到header的before位置,而LinkedHashIterator遍历的方式是从header.after开始遍历,先得到最近使用的Entry
最近使用:accessOrder为true时,get(Object key)方法会导致Entry最近使用put(K key, V value)/putForNullKey(value)只有是覆盖操作时会导致Entry最近使用。它们都会触发recordAccess方法从而导致Entry最近使用
删除
LinkedHashMap没有重写remove(Object key)方法,重写了被remove调用的recordRemoval方法,删除了双向链表中的before和after。
HahsMap remove(Object key)把数据从横向数组 * 竖向next链表里面移除之后(就已经完成工作了,所以HashMap里面recordRemoval是空的实现调用了此方法
LinkedHashMap的遍历
总结
1、什么是LRU+插入顺序?
put(K key, V value)/putForNullKey(value)只有是覆盖操作时会导致Entry最近使用,即为插入顺序;accessOrder为true时,get(Object key)方法会导致Entry最近使用,即为LRU
2、LinkedHashMap和HashMap的区别
- LinkedHashMap继承HashMap,结构2里数据结构的变化交给HashMap就行了。
- 结构1里数据结构的变化就由LinkedHashMap里重写的方法去实现。
- 简言之:LinkedHashMap比HashMap多维护了一个链表。
相关推荐
### Map 总结:原理与使用详解 #### 一、Map 概述 **Map** 是 C++ STL(Standard Template Library)中的一种关联容器,它主要用于存储...通过理解其原理及使用方法,可以在实际开发中更高效地运用这一强大的工具。
- 使用Eclipse创建新的Map-Reduce项目。 - 编写Map和Reduce函数。 - 配置作业参数,如输入输出路径等。 **4. 提交和运行作业** - 将编写的Map-Reduce应用程序提交到Hadoop集群。 - 监控作业的执行进度和状态。 ##...
2. TileMap的工作原理: TileMap通常由一个二维数组表示,每个元素对应一个瓷砖ID。这些ID与预设的瓷砖图像库相联系,使得开发者可以通过简单的数据操作就能改变关卡布局。在Unity、Cocos2d-x等引擎中,都有内置的...
### Depthmap10软件使用教程知识点汇总 #### 一、深度了解Depthmap10 - **简介** - **发布日期与版本**:2010年9月发布的Depthmap10版本为10.08.00r。 - **作者**:Joao Pinelo 和 Alasdair Turner。 - **目的**...
mAP实现原理及计算方式讲解.txt
### END_MESSAGE_MAP宏的内部实现原理深度解析 在深入探讨`END_MESSAGE_MAP`宏的内部实现之前,我们首先需要理解MFC(Microsoft Foundation Classes)框架如何处理Windows消息。MFC框架设计了一套高效的机制来映射...
Turbo码是一种高效的纠错编码...总之,Turbo码的MAP译码原理是现代通信系统中纠错编码的重要组成部分,它通过迭代和软信息交换实现了高错误纠正能力。理解并掌握这一技术对于设计高效、可靠的通信系统具有重要意义。
这两种贴图方法都用于模拟物体表面的微小不平,从而在视觉上增加深度和复杂性,但它们的工作原理和应用方式有所不同。 首先,让我们了解浮雕凹凸贴图(BumpMap)。BumpMap是一种灰度图像,其中的每个像素值代表对应...
将创建的数据表打包成Cognos包,并命名为“cognos map”,以便在Report Studio中使用。 #### Step 3: 运行 Report Studio 选择已发布的包,导入所需的数据源。 #### Step 4: 添加数据元素 在Report Studio中,从...
自定义`Map`的主要目的是为了学习和理解数据结构的工作原理,以及如何在C++中实现这些数据结构。尽管`std::map`已经提供了一套完整的功能,但自己动手实现可以帮助开发者深入理解底层的红黑树(Red-Black Tree)或...
MybatisPlus多数据源原理及使用注意点 MybatisPlus多数据源原理及使用注意点.pdf 文件提供了关于MybatisPlus多数据源的详细信息,包括原理、配置方式、使用注意点等内容。下面是根据文件内容生成的相关知识点: 一...
总的来说,电机效率MAP的绘制是一个结合了物理原理、数据处理和可视化技术的过程,对于理解和优化电机性能具有深远的影响。"map.zip"提供的工具或许能简化这一过程,使得非专业用户也能方便地分析电机的效率特性。
在实际使用"map.m"这个工具时,用户可能需要输入电机的电气和机械参数,如额定功率、电压、电流、转速等,并指定一系列工作点进行计算。然后,程序会自动生成对应的效率Map图形,便于用户直观地理解和分析电机的性能...
本文将深入探讨 `map` 的用法,包括它的定义、工作原理以及在不同编程语言中的应用。 `map` 函数的初衷是将一个函数应用到一个集合(如列表、数组或元组)的所有元素上,然后返回一个新的集合,其中包含了原集合...
STL(Standard Template Library,标准模板库)是C++编程语言中的一个重要组成部分,它提供了一系列高效、可重用的数据结构和算法。...通过分析提供的源代码,你可以深入理解STL map的工作原理和在实际编程中的应用。
了解其工作原理和使用技巧对于编写高效代码至关重要。在实际项目中,根据需求选择合适类型的Map,例如需要保持插入顺序时可以选择LinkedHashMap,需要排序则选择TreeMap,追求效率则优先考虑HashMap。
在Java编程语言中,`Map`接口是集合框架的重要组成部分,它存储键值对,其中每个键都是唯一的。`containsKey()`方法是`Map`接口中的一个关键方法,用于检查给定的键是否存在于该映射中。在这个场景中,我们将深入...
同时,对于低内存配置的设备,合理使用RAMMAP可以显著改善系统的响应速度。 总的来说,RAMMAP是一款强大的内存分析和优化工具,通过简单的操作,用户就能实现对系统内存的有效管理,提高电脑运行效率。无论是日常...