hashmap原理

HashMap中 get(K key) 和 put(K key,V value) 的具体过程

…衆ロ難τιáo~ 提交于 2020-03-22 18:08:21
说在前面 本文包含手写泛型HashMap<K,V>为简化版,仅为理解 HashMap 的 get() 和put() 方法的工作过程,非Java源码。 get(K key) 原理 先计算出key对应的hash值 int hash = key.hashCode(); //此处的 hashCode() 方法为 Object对象 所属方法,默认都有 //自定义的类需要覆写该方法 对超出数组范围的hash值进行处理 hash = (hash >>> 16)^hash;//java内部自做的优化,为了使hash值更加均衡,减少冲突 int index = hash & (table.length - 1);//对下标进行合理化,以免下标越界 //这样做可以使index在数组长度范围内的原因或者一个前提是,这里的数组的长度一定是2的n次方, //这样table.length - 1 在二进制情况下,除最高位,其余低位为一定是1,用hash与这样的一个数进行与操作 //即只保留了hash的二进制的低位,就会使hash的范围一定小于数组长度 根据正确的hash值(下标值)找到所在的链表的头结点 Entry<K,V> node = table[index]; 遍历链表,如果key值相等,返回对应的value值,否则返回null while(node != null){ if(node.key

jdk1.8 HashMap扩容原理详解

老子叫甜甜 提交于 2020-03-22 07:14:18
JDK1.7中,resize时,index取得时,全部采用重新hash的方式进行了。JDK1.8对这个进行了改善。 以前要确定index的时候用的是(e.hash & oldCap-1),是取模取余,而这里用到的是(e.hash & oldCap),它有两种结果,一个是0,一个是oldCap, 比如oldCap=8,hash是3,11,19,27时,(e.hash & oldCap)的结果是0,8,0,8,这样3,19组成新的链表,index为3;而11,27组成新的链表,新分配的index为3+8; JDK1.7中重写hash是(e.hash & newCap-1),也就是3,11,19,27对16取余,也是3,11,3,11,和上面的结果一样,但是index为3的链表是19,3,index为3+8的链表是 27,11,也就是说1.7中经过resize后数据的顺序变成了倒叙,而1.8没有改变顺序。 原理: 我们使用的是2次幂的扩展(指长度扩为原来2倍),所以,元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。看下图可以明白这句话的意思,n为table的长度,图(a)表示扩容前的key1和key2两种key确定索引位置的示例,图(b)表示扩容后key1和key2两种key确定索引位置的示例,其中hash1是key1对应的哈希与高位运算结果。 元素在重新计算hash之后

ConcurrentHashMap源码解析(1.8)

末鹿安然 提交于 2020-03-20 07:58:47
一、简介 上篇文章 详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理。 首先在看本文之前,希望对HashMap有一个详细的了解。不然看直接看ConcurrentHashMap的源码还是有些费劲的。 相信对HashMap,HashTable有一定了解,应该知道HashMap是不具备线程安全性的,在resize时会丢数据(JDK8),而HashTable虽然保证了线程安全性,但是其是通过给每个方法加Synchronized关键字达到的同步目的。但是都知道Synchronized在竞争激烈的多线程并发环境中,在性能上的表现是非常不如人意的。那在高并发环境中HashMap如何保证线程安全而又不浪费太多性能呢?答案就是Java J.U.C并发包中的ConcurrentHashMap。 依然开局一张图。JDK8中的ConcurrentHashMap数据结构。 呃呵,和HashMap的结构是一样的,没错在数据结构层面,ConcurrentHashMap和HashMap是完全一样的。有了这个基础继续往下看。 二、历史版本 ConcurrentHashMap的历史版本大致分界线在JDK8。也就是可以分为JDK8和JDK8以前版本。 数据结构的区别 在JDK8之前HashMap没有引入红黑树,同样的ConcurrentHashMap也没有引入红黑树

HashMap的实现原理

蓝咒 提交于 2020-03-13 09:24:54
一,前言 1.1,概述 ​ 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射(K-V)。Java提供了专门的集合类用来存放这种对象关系的对象,即 java.util.Map 接口。 Collection 中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。 Map 中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键(K)可以找对所对应的值(V)。 Collection 中的集合称为单列集合, Map 中的集合称为双列集合。 需要注意的是, Map 中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。 ​ 通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。 HashMap<K,V> :存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。 LinkedHashMap<K,V> :HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法

JDK 1.8 HashMap 扩容源码详解

独自空忆成欢 提交于 2020-03-05 13:19:02
作为开发人员,千万不能停留在实现功能上,一定要提升到性能方面上。这需要我们不断的实践,学习源码, 根据底层实现原理,来做出最好的操作。 就HashMap而言,一定是我们常用的集合,它有着查询速度是 O(1) 的特点,特就是快速获取键值对结果。 但是如果不去读源码,就不会知道它的默认的大小是capcity 16,负载因子是 0.75 ,在hashmap中存放 超过 caticy * 负载因子,则需要去扩容,扩容的时候,是需要消耗很多资源, 因为扩容是扩了两倍 ,然后需要将原来的复制到新的扩容后的数组里边。 这个慢的体验就是你想要 put 的时候,如果触发了 扩容 resize() ,则需要等到扩容才能添加进去,注意,现在1.8的源码里边,扩容,就直接把原来的数据重新hash 然后给到扩容后的数组。 接下来看源码: final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; if (oldCap > 0) { if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE;

ConcurrentHashMap源码解析

北慕城南 提交于 2020-03-02 10:33:41
ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现 ConcurrentHashMap在并发编程的场景中使用频率非常之高,本文就来分析下ConcurrentHashMap的实现原理,并对其实现原理进行分析(JDK1.7). ConcurrentHashMap实现原理   众所周知,哈希表是中非常高效,复杂度为O(1)的数据结构,在Java开发中,我们最常见到最频繁使用的就是HashMap和HashTable,但是在线程竞争激烈的并发场景中使用都不够合理。    HashMap :先说HashMap,HashMap是 线程不安全 的,在并发环境下,可能会形成 环状链表 (扩容时可能造成,具体原因自行百度google或查看源码分析),导致get操作时,cpu空转,所以,在并发环境中使用HashMap是非常危险的。    HashTable : HashTable和HashMap的实现原理几乎一样,差别无非是 1.HashTable不允许key和value为null;2.HashTable是线程安全的。 但是HashTable线程安全的策略实现代价却太大了,简单粗暴,get/put所有相关操作都是synchronized的,这相当于给整个哈希表加了一把 大锁 ,多线程访问时候,只要有一个线程访问或操作该对象,那其他线程只能阻塞

HashMap(一)基础入门

人盡茶涼 提交于 2020-02-13 10:58:13
1.数组的优势/劣势 数组的内存空间是连续的 特点:索引速度快 劣势:增加、删除数据时,浪费性能 2.链表的优势/劣势 链表不是连续的内存,每一块内存中有一个引用保存下一个内存的地址。 优势:增加、删除数据时,效率高 劣势:如果要访问最后一个元素,只能从头依次访问每一个内存,查询效率低 3.有没有一种方式整合两种数据的优势? 散列表。 整合了数组的快速索引,和链表的动态扩容 4.什么是哈希? 核心理论:Hash也称散列、哈希,基本理论就是把 任意长度 的输入,通过Hash算法变成 固定长度 的输出。 这个映射的规则就是对应的Hash算法,而原始数据映射后的二进制串就是哈希值。 Hash的特点: 从hash值不可以反向推导出原始的数据 输入的数据的微小变化会得到完全不同的hash值,相同的数据会得到相同的值 哈希算法的执行效率高效,长的文本也能快速计算出哈希值。 hash算法的冲突概率要小 由于hash的原理是将输入空间的值映射成hash空间内,而hash值的空间远小于输入的空间。 根据抽屉原理,一定会在不同的输入被映射成相同输出情况。 抽屉原理:桌上有十个苹果 ,要把这十个苹果放到九个抽屉里,无论怎么放,我们会发现至少会有一个抽屉里面放不少于两个苹果。 这一现象就是我们所说的“抽屉原理” 来源: CSDN 作者: 梨子果果哟 链接: https://blog.csdn.net/qq

HashMap中的红黑树实现原理

爱⌒轻易说出口 提交于 2020-02-12 14:32:09
1.为什么要引入红黑树? 在jdk1.8 引入了红黑树的设计,当冲突的链表长度超过 8 个时,链表结构就会转为红黑树结构,这样做的好处是避免在极端条件的情况下冲突链表过长而导致查询效率非常慢。 红黑树查询 :其访问性能近似于折半查找,时间复杂度O(logn); 链表查询 :这种情况下,需要遍历全部元素才行,时间复杂度O(n); 2.红黑树的简单概念 红黑树是一种近似平衡的二叉查找树,其主要的优点就是 平衡 ,即左右子树高度几乎一致,以此来防止树退化为链表,通过这种方式来保障查找的时间复杂度为log(n); 红黑树的基本特性 1.每个节点要么是黑色,要么是红色,但根节点必须是黑色的; 2.每个红色节点的两个子节点必须是黑色的; 3.红色节点不能连续(即红色节点的孩子和父亲都不能是红色的); 4.从任意节点到其子树中每个叶子结点的路径都包含相同数量的黑色节点; 5.所有的叶子节点都是黑色的。 6.新加入到红黑树的节点为红色节点。 在树的结构发生改变时,往往会破坏条件3,4,需要通过调整使得查找树重新满足红黑树的条件。 3.红黑树的调整方式 调整可以分为两类: 一类是颜色调整,即改变某个节点的颜色,这种比较简单,直接将节点颜色进行转换即可;另一类是结构调整,改变检索树的结构关系。结构调整主要包含两个基本操作:左旋(Rotate Left),右旋(Rotate Right)。 1. 左旋

ConcurrentHashMap源码解析 JDK8

*爱你&永不变心* 提交于 2020-01-14 17:33:54
一、简介 上篇文章 详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理。 首先在看本文之前,希望对HashMap有一个详细的了解。不然看直接看ConcurrentHashMap的源码还是有些费劲的。 相信对HashMap,HashTable有一定了解,应该知道HashMap是不具备线程安全性的,在resize时会丢数据(JDK8),而HashTable虽然保证了线程安全性,但是其是通过给每个方法加Synchronized关键字达到的同步目的。但是都知道Synchronized在竞争激烈的多线程并发环境中,在性能上的表现是非常不如人意的。那在高并发环境中HashMap如何保证线程安全而又不浪费太多性能呢?答案就是Java J.U.C并发包中的ConcurrentHashMap。 依然开局一张图。JDK8中的ConcurrentHashMap数据结构。 呃呵,和HashMap的结构是一样的,没错在数据结构层面,ConcurrentHashMap和HashMap是完全一样的。有了这个基础继续往下看。 二、历史版本 ConcurrentHashMap的历史版本大致分界线在JDK8。也就是可以分为JDK8和JDK8以前版本。 数据结构的区别 在JDK8之前HashMap没有引入红黑树,同样的ConcurrentHashMap也没有引入红黑树

java笔记整理

我与影子孤独终老i 提交于 2020-01-10 03:48:31
基本概念 操作系统中 heap 和 stack 的区别 什么是基于注解的切面实现 什么是 对象/关系 映射集成模块 什么是 Java 的反射机制 什么是 ACID BS与CS的联系与区别 Cookie 和 Session的区别 fail-fast 与 fail-safe 机制有什么区别 get 和 post请求的区别 Interface 与 abstract 类的区别 IOC的优点是什么 IO 和 NIO的区别,NIO优点 Java 8 / Java 7 为我们提供了什么新功能 什么是竞态条件? 举个例子说明。 JRE、JDK、JVM 及 JIT 之间有什么不同 MVC的各个部分都有那些技术来实现?如何实现? RPC 通信和 RMI 区别 什么是 Web Service(Web服务) JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 WEB容器主要有哪些功能? 并请列出一些常见的WEB容器名字。 一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制 简单说说你了解的类加载器。是否实现过类加载器 解释一下什么叫AOP(面向切面编程) 请简述 Servlet 的生命周期及其相关的方法 请简述一下 Ajax 的原理及实现步骤 简单描述Struts的主要功能 什么是 N 层架构 什么是CORBA?用途是什么 什么是Java虚拟机