容器HashMap原理(学习)
一、概述
基于哈希表的 Map 接口的非同步实现,允许使用 null 值和 null 键,不保证映射的顺序
二、数据结构
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体;HashMap 底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个 HashMap 的时候,就会初始化一个数组。

三、源码解读
put =>
当我们往 HashMap 中 put 元素的时候,先根据 key 的 hashCode 重新计算 hash 值,根据 hash 值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
get=>
在 HashMap 中要找到某个元素,需要根据 key 的 hash 值来求得对应数组中的位置。
对于任意给定的对象,只要它的 hashCode() 返回值相同,那么程序调用 hash(int h) 方法所计算得到的 hash 码值总是相同的。我们首先想到的就是把 hash 值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。
而 HashMap 底层数组的长度总是 2 的 n 次方,这是 HashMap 在速度上的优化;
归纳:
HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据 hash 算法来决定其在数组中的存储位置,在根据 equals 方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry 时,也会根据 hash 算法找到其在数组中的存储位置,再根据 equals 方法从该位置上的链表中取出该Entry。
四、HashMap 什么时候进行扩容呢(resize)
当 HashMap 中的元素个数超过数组大小 *loadFactor时,就会进行数组扩容,loadFactor的默认值为 0.75,默认情况下,数组大小为 16,那么当 HashMap 中元素个数超过 16*0.75=12 的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知 HashMap 中元素的个数,那么预设元素的个数能够有效的提高 HashMap 的性能。
五、Fail-Fast 机制
java.util.HashMap 不是线程安全的,因此如果在使用迭代器的过程中有其他线程修改了 map,那么将抛出 ConcurrentModificationException,这就是所谓 fail-fast 策略,迭代器的快速失败行为应该仅用于检测程序错误
六、遍历方式
效率较高的:
Map map = new HashMap();效率较低的:
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
}
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Object key = iter.next();
Object val = map.get(key);
}
foreach方式:
for(Entry<String, String> entry:hashmap.entrySet()){
System.out.println(entry.getKey()+"-->"+entry.getValue());
}
容器HashMap原理(学习)的更多相关文章
- java容器HashMap原理
1.为什么需要HashMap 前面我们说了ArrayList和LinkedList,它们对容器内的对象都能实现增.删.改.查.遍历等操作, 并且对应不同的情况,我们可以选择不同的List,用以提高效率 ...
- 基于AOP和HashMap原理学习,开发Mysql分库分表路由组件!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 什么?Java 面试就像造火箭 单纯了! 以前我也一直想 Java 面试就好好面试呗 ...
- 容器ConcurrentHashMap原理(学习)
一.概述 HashMap 是非线程安全的,在不考虑性能问题的时候,我们的解决方案有 Hashtable 或者Collections.synchronizedMap(hashMap),这两种方式基本都是 ...
- 理解java容器底层原理--手动实现HashMap
HashMap结构 HashMap的底层是数组+链表,百度百科找了张图: 先写个链表节点的类 package com.xzlf.collection2; public class Node { int ...
- Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory
从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...
- IIS原理学习
IIS 原理学习 首先声明以下内容是我在网上搜索后整理的,在此只是进行记录,以备往后查阅只用. IIS 5.x介绍 IIS 5.x一个显著的特征就是Web Server和真正的ASP.NET Appl ...
- spring容器IOC原理解析
原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean ...
- docker容器网络通信原理分析
概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两 ...
- docker容器网络通信原理分析(转)
概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两 ...
随机推荐
- <Linux> 下安装和卸载JDK
安装 下载jdk https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 在local ...
- 字符串str.format()方法的个人整理
引言: 字符串的内置方法大致有40来个,但是一些常用的其实就那么20几个,而且里面还有类似的用法,区分度高比如isalpha,isalnum,isdigit,还有一些无时不刻都会用到的split切分, ...
- day21 04 三级菜单
day21 04 三级菜单 1.使用递归调用的方法 整体代码类型比较简单如下: menu={'北京':{'海淀':{'a':{},'h':{},'c':{}},'昌平':{'沙河':{},'天通苑': ...
- Linux 下 Jenkins安装
Jenkins介绍 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1.持续的软件版本发布/测试项目. 2.监控外部调用执行的工作. 安装环境 操作系统:lin ...
- C++标准模板库 ——堆栈使用
include using namespace std; stack S; S.push(i); S.pop(); int x = S.top(); ```
- 史上最全Java多线程面试题及答案
多线程有什么用? 线程和进程的区别是什么? Java实现线程有哪几种方式? 启动线程方法start()和run()有什么区别? 怎么终止一个线程?如何优雅地终止线程? 一个线程的生命周期有哪几种状态? ...
- loadrunner-3个难点
1.loadrunner 监控windows资源 2.loadrunner如何实现如下: 1.1.1.1 场景一 10进程同时新增用户 测试场景说明:10进程新增用户, 第一个进程从1到1000,第二 ...
- multi cookie & read bug
js cookie multi cookie & read bug document.cookie; // "access_token_test=eyJhbGciOiJIUzI1Ni ...
- Rooks-LightOj1005(规律)
A rook is a piece used in the game of chess which is played on a board of square grids. A rook can o ...
- Linux下启用IP转发功能(主要针对Ubuntu的使用)
说明:以下的操作只要在Linux下都是通用的. Linux发行版默认情况下是不开启IP转发功能的.如果架设一个Linux路由或者VPN服务就需要开启该服务. 1.通过访问sysctl的内核ipv4.i ...