HashMap 底层分析
以下基于 JDK1.7 分析

如图所示,HashMap底层是基于数组和链表实现的,其中有两个重要的参数:
---容量
---负载因子
容量的默认大小是16,负载因子是0.75,当HashMap的size > 16* 0.75时就会发生扩容(容量和负载因子都可以自由调整)
put方法
首先会将传入的key做hash运算计算出hashcode,然后根据数组长度取模计算出在数组中的index下标
由于在计算中位运算比取模运算效率高的多,所以HashMap规定数组的长度为2^n,这样用2^n -1做位运算与取模效果一致,并且效率还要高处许多。
由于数组的长度有限,所以难免会出现不同的key通过运算得到的index相同,这种情况可以利用链表来解决,HashMap会在table[index]处形成链表,采用头插法将数据插入到链表中。
get方法
get和put类似,也是将传入的key计算出index,如果该位置上是一个链表就需要遍历整个链表,通过key.equals(k)来找到对应的元素。
Iterator<Map.Entry<String, Integer>> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {
Map.Entry<String, Integer> next = entryIterator.next();
System.out.println("key=" + next.getKey() + " value=" + next.getValue());
}
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
System.out.println("key=" + key + " value=" + map.get(key)); }
map.forEach((key,value)->{
System.out.println("key=" + key + " value=" + value);
});
强烈建议使用第一种 EntrySet 进行遍历。
第一种可以把 key value 同时取出,第二种还得需要通过 key 取一次 value,效率较低, 第三种需要 JDK1.8 以上,通过外层遍历 table,内层遍历链表或红黑树。
notice
在并发环境下HashMap容易出现死循环
并发场景发生扩容,调用resize()方法里的rehash()时,容易出现环形链表,这样当获取一个不存在的key时,计算出的index正好是环形链表的下标时就会出现死循环。
所以 HashMap 只能在单线程中使用,并且尽量的预设容量,尽可能的减少扩容。
在 JDK1.8 中对 HashMap 进行了优化: 当 hash 碰撞之后写入链表的长度超过了阈值(默认为8),链表将会转换为红黑树。
假设 hash 冲突非常严重,一个数组后面接了很长的链表,此时重新的时间复杂度就是 O(n) 。
如果是红黑树,时间复杂度就是 O(logn) 。
大大提高了查询效率。
HashMap 底层分析的更多相关文章
- HashMap底层分析
以下基于 JDK1.7 分析. 如图所示,HashMap 底层是基于数组和链表实现的.其中有两个重要的参数: 容量 负载因子 容量的默认大小是 16,负载因子是 0.75,当 HashMap 的 si ...
- HashMap底层原理分析(put、get方法)
1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那ha ...
- Java——HashMap底层源码分析
1.简介 HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的. HashMap 最多只允许一条记录的key为 nu ...
- ArrayList、LinkedList、HashMap底层实现
ArrayList 底层的实现就是一个数组(固定大小),当数组长度不够用的时候就会重新开辟一个新的数组,然后将原来的数据拷贝到新的数组内. LinkedList 底层是一个链表,是由java实现的一个 ...
- HashMap的分析(转)
一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了不同步和允许使用 null 之外,HashMap ...
- HashMap底层结构、原理、扩容机制
https://www.jianshu.com/p/c1b616ff1130 http://youzhixueyuan.com/the-underlying-structure-and-princip ...
- HashMap底层数据结构和算法解析
1.Hash Map的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过8时,链表转换为红黑树. transient Node<K,V>[] ta ...
- hashMap 底层原理+LinkedHashMap 底层原理+常见面试题
1.源码 java1.7 hashMap 底层实现是数组+链表 java1.8 对上面进行优化 数组+链表+红黑树 2.hashmap 是怎么保存数据的. 在hashmap 中有这样一个结构 ...
- [转]java 的HashMap底层数据结构
java 的HashMap底层数据结构 HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-v ...
随机推荐
- 线性筛prime/phi/miu/求逆元模板
这绿题贼水...... 原理我不讲了,随便拿张草稿纸推一下就明白了. #include <cstdio> using namespace std; ; int su[N],ans,top; ...
- 利用pandas对numpy数组进行简单的科学计算
二维数组转换为DataFrame pandas可直接进行科学计算形式: import numpy as np import pandas as pd a = [1,2,3] b = [4,5,6] # ...
- Django(十)COOKIE和session
https://www.cnblogs.com/haiyan123/p/7763169.html from django.shortcuts import render,redirect # Crea ...
- 在views中引用UserProfile报错RuntimeError: Model class apps.users.models.UserProfile doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
如图报错,在settings中,该加的也加了啊! 显然类似于网上最容易遇到的解决方案如下图,是没有任何意义的 只要在view中有 from .models import UserProfile,Ver ...
- 使用海康的某款摄像头以及v4l2的经验
Video Capture模式下发现使用MJPEG流和YUYV流相同分辨率视野却不同. 最后没找到怎么设物理窗口或图片窗口的方法,做实验知道了为什么. 设为1280×720 YUYV实际物理窗口是19 ...
- Elastic 基础篇(2)
1.基本概念 1)Elastic和RDMS对比 RDMS Elastic 数据库database 索引index 表table 类型type 行row 文档document 列column 字段fie ...
- ArrayList 实现随机点名
package lijun.cn.demo1; import java.util.ArrayList; import java.util.Random; public class CallName { ...
- springboot学习笔记-5 springboot整合shiro
shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和sh ...
- Hadoop序列化-流量汇总案例
Hadoop序列化案例-流量汇总需求 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Hadoop序列化 1>.为什么要序列化 一般来说,“活的”对象只生存在内存里,关机断 ...
- mac 安装pip
mac 安装pip报错 bogon:~ root# sudo easy_install pip Searching for pip Reading https://pypi.python.org/si ...