HashMap解析

HashMap底层实现原理解析

1、数组结构: 存储区间连续、内存占用严重、空间复杂度大

优点:随机读取和修改效率高,原因是数组是连续的(随机访问性强,查找速度快)

缺点:插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中都要往后移动,且大小固定不易动态扩展。

2、链表结构:存储区间离散、占用内存宽松、空间复杂度小

优点:插入删除速度快,内存利用率高,没有固定大小,扩展灵活

缺点:不能随机查找,每次都是从第一个开始遍历(查询效率低)

3、哈希表结构:结合数组结构和链表结构的优点,从而实现了查询和修改效率高,插入和删除效率也高的一种数据结构

常见的HashMap就是这样的一种数据结构


HashMap中的put()和get()的实现原理:

1、map.put(k,v)实现原理

(1)首先将k,v封装到Node对象当中(节点)。

(2)然后它的底层会调用K的hashCode()方法得出hash值。

(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

2、map.get(k)实现原理

(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。

(2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

相比 jdk1.7 的 HashMap 而言,jdk1.8最重要的就是引入了红黑树的设计,当hash表的单一链表长度超过 8 个的时候,链表结构就会转为红黑树结构。



HashMap常用参数

capacity: 当前数组的容量,默认为16。可以扩容,扩容后数组大小*2。

loadFactor: 负载因子,默认为0.75.

threshold: 扩容的阈值,= capacity * loadFactor。



ConcurrentHashMap

JDK 1.7版本之前,其有多个segment组成。每个segment均继承ReentrantLock并单独枷锁,所以每次进行加锁操作时锁住的都是一个segment。这样只要保证每个segment都是安全的,也就实现了全局的线程安全。其中有个参数叫conccurrencyLevel,默认值16,指16个segment,最多支持16个线程并发执行写操作,只要他们操作的数据分布在不同的segment上。conccurrencyLevel只能在初始化设置,一旦初始化后就不可以更改。

JDK 1.8之后,ConcurrentHashMap弃用了segment,改用Synchronized+CAS(CAS介绍)实现对多线程的安全操作。同时引入了红黑树结构。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

推荐阅读更多精彩内容

  • 注:本文是以Android中的HashMap进行讲解 问题: 1、HashMap采用的是什么数据结构?2、Hash...
    jxiang112阅读 762评论 0 1
  • 带着问题去学习一个知识点的时候往往会更加记忆深刻,所以本篇文章主要来解答以下几个问题: 1.HashMap的工作原...
    JackDaddy阅读 409评论 0 3
  • HashMap源码解析 之前面试的时候发现很多的公司对于hashMap的源码这一块问的比较多,所以自己在看Hash...
    孑鼠阅读 362评论 0 0
  • 前言 上篇文章讲解了JDK1.7中的HashMap源码, 主要采用数组+链表来实现, 根据元素的hash计算出来的...
    海之韵Baby阅读 382评论 0 0
  • 一、概述 HashMap的底层数据结构是数组,但是数组中存放的并不是一个对象而是链表。所以也可以成HashMap的...
    史云龙阅读 447评论 0 0