面试官!你又双叒叕问HashMap!

2024-04-02 21:38
文章标签 hashmap 面试官 又双叒

本文主要是介绍面试官!你又双叒叕问HashMap!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HashMap的数据结构(图解+源码分析)

HashMap快速索引

数组

定义:连续的内存,具有共同特性的数据

现有一个8个元素的空数组,如下图
在这里插入图片描述
向数组尾部添加数据:
在这里插入图片描述
向数组中插入节点:

如果项目把475插入到下标为1的位置,就要把275的下标位置向后移一位
在这里插入图片描述
优点:连续内存,通过数组下标可以快速寻址

缺点:中间插入节点比较慢

单链表

定义:任意内存单元通过指针连接每个结点,存放线性表中的数据

现有如下三个结点的单链表:
在这里插入图片描述
向单链表尾部添加数据:把next指针指向下一个节点的Data域
在这里插入图片描述
向点链表中插入节点:

假设在“275”和“297”之间插入新的结点,那么只需把“297”的next指向新结点的data域,然后新结点的next指向“297”的data域。无需同数组那样调整后面结点的位置。
在这里插入图片描述
优点:插入和删除数据方便

缺点:单链表查询某个结点,需要从头结点开始遍历整个链表,所以单链表的查询效率比较低

HashMap如何插入数据(图解+源码分析pos)

建立插入值和数组所在下标的位置(pos = key % size key: 插入数据的内容;size:数组的大小

比如要将100,201,303这三个数据插入到一个长度为10的以链表特性声明的数组

pos1 = 100 % 10 = 0

pos2 = 201 % 10 = 1

pos3 = 303 % 10 = 3
在这里插入图片描述
HashMap的构造函数:

/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted}

HashMap插入函数(put):

public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

其中table是 “transient Node<K,V>[]”单链表结构的数组

其中resize()

/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;else {               // zero initial threshold signifies using defaultsnewCap = DEFAULT_INITIAL_CAPACITY;//16newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);//12}threshold = newThr;//12

为什么初始化容量是2的倍数(源码分析)

else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >= DEFAULT_INITIAL_CAPACITY)newThr = oldThr << 1; // double threshold
  1. 计算机申请内存是2的倍数,可以避免内存碎片

  2. 移位操作效率高

  3. 参与到hash运算中提高散列度

    putVal()中:

    (p = tab[i = (n - 1) & hash])
    

    举例:

    n = 16 (10000)

    i=(n-1) : 0000 1111

    hash1 : 0000 0001 -> 0000 0001

    hash2 : 0001 0000 -> 0000 0000

    若:n = 15 (01111)

    i=(n-1) : 0000 1110

    hash1 : 0000 0001 -> 0000 0000

    hash2 : 0001 0000 -> 0000 0000

    所以HashMap初始化数组使用2的倍数(因为2的倍数减1,后面的全1)可以提高散列度和降低冲突

HashMap如何解决Key冲突(图解+源码分析)

上一部分,咱们插入的数据是没有冲突的,如果我们插入200,那么pos取模后也是0,和100这个结点冲突了,HashMap针对这种冲突问题,通过单链表解决
在这里插入图片描述
查询到0的时候,就可以定位到100和200了,

但是问题来了,如果以这种单链表的形式解决冲突问题,那么查询起来会很慢!

为了解决上面的这个问题JDK1.8中引入了“红黑树”(高度平衡的平衡二叉树)这一概念,因为二叉树的查询效率是树的深度,显然查询效率比单链表高。
在这里插入图片描述

HashMap如何扩容(源码分析)

HashMap查询与删除

HashMap序列化(源码分析)

总结

  1. HashMap的数据结构包括数组、单链表、红黑树;

  2. 数组容量为2的倍数:

    ​ a.提高运算速度,

    ​ b.增加散列度,降低冲突,

    ​ c.减少内存碎片 。

  3. 通过hash函数和pos = key % size 确定数据插入位置,hashcode的高16位和低16位进行异或取模,增加散列度,降低冲突;

  4. 当两个及两个以上的key相同且data不同的时候(插入冲突),通过单链表解决冲突,如果链表的长度超过(TREEIFY_THRESHOLD = 8), 将单链表转化成红黑树以提高查询效率;

  5. 扩容条件:实际节点数大于等于容量的3/4;扩容后的数据排布:1.原下标的位置;2.原下标+原容量的位置

  6. 序列化:只存储了数组的容量、实际结点数量和各个结点的key,value值.

还有 HashMap如何扩容(源码分析) 、 HashMap查询与删除 、HashMap序列化(源码分析)这三部分在整理中~觉得看完有帮助的小伙伴,可以关注小名或者收藏此文等待后期更新哈😁

这篇关于面试官!你又双叒叕问HashMap!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/871121

相关文章

【吊打面试官系列-Redis面试题】说说 Redis 哈希槽的概念?

大家好,我是锋哥。今天分享关于 【说说 Redis 哈希槽的概念?】面试题,希望对大家有帮助; 说说 Redis 哈希槽的概念? Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分 hash 槽。

HashMap中常用的函数

假设如下HashMap<String, Integer> map = new HashMap<>();获取value值1、返回key为a的valueget(a)2、返回key为a的value,若没有该key返回0getOrDefault(a,0)新增键值对1、新增键值对(a,1)put(a,1)2、如果key为a的键不存在,则存入键值对(a,1)putIfAbsent(a,1)3

hashmap的存值,各种遍历方法

package com.jefflee;import java.util.HashMap;import java.util.Iterator;import java.util.Map;public class HashmapTest {// 遍历Hashmap的四种方法public static void main(String[] args) {//hashmap可以存一个null,把

面试官:synchronized的锁升级过程是怎样的?

大家好,我是大明哥,一个专注「死磕 Java」系列创作的硬核程序员。 回答 在 JDK 1.6之前,synchronized 是一个重量级、效率比较低下的锁,但是在JDK 1.6后,JVM 为了提高锁的获取与释放效,,对 synchronized 进行了优化,引入了偏向锁和轻量级锁,至此,锁的状态有四种,级别由低到高依次为:无锁、偏向锁、轻量级锁、重量级锁。 锁升级就是无锁 —>

【Unity面经】实习篇:面试官常问的一百个面试题

👨‍💻个人主页:@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 专栏交流🧧🟥Unity100个实战基础✨🎁🟦 Unity100个精华一记✨🎁🟩 Unity50个demo案例教程✨🎁🟨 Unity100个精华细节BUG✨🎁🟨 Unity100个面试题✨🎁 文章

容器第五课,Map和HashMap的基本用法,hashMap和HashTable的区别

Map接口 实现Map接口的类用来存储键(Key) --- 值(value)对。 Map接口的实现类有HashMap和TreeMap类 Map类中存储的键---值对通过键来标识,所以键值不能重复 package com.pkushutong.Collection;import java.util.HashMap;import java.util.Map;/*** 测试Map的基本用法

面试:HashMap

文章引用: http://www.importnew.com/7099.html https://blog.csdn.net/niuwei22007/article/details/52005329 HashMap的工作原理是近年来常见的Java面试题。几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么

HashMap 源码分析(删除+总结)JDK1.8

文章来源: 1 https://segmentfault.com/a/1190000012926722#articleHeader7 2 https://www.zhihu.com/question/20733617 3 https://tech.meituan.com/java-hashmap.html 4 https://www.zhihu.com/question/5752

作为面试官的一点点感悟,谈谈技术人的成长之路

因为工作上的原因,做过几次面试官,面试的同学有应届生,也有工作3-5年的老技术人。最近也频繁作为面试官帮助筛选候选人,中间有很多值得深思的东西,我记录了下来分享给大家。 以下观点仅为个人观点,不代表任何公司的立场。        01 面试不是简单的你问我答 一般来讲,作为面试官和候选人进行沟通的第一个问题是一般是自我介绍,整个自我介绍的情况应该控制在2分钟左右,阐述自己的教育背景,项目经历

【对线面试官】阿里面试经历,有些人走一步看一步就挂了

点击上方蓝色字体,选择“设为星标” 回复”资源“获取更多资源 这个其实说来就话长了。是小编曾经面试阿里妈妈的经历。 这次面试最终在HR面挂掉,以至于后面回忆起来,仍然是一桩美谈。 这次面试长达一个月之久,共经历了4轮技术面,1轮HR。前四轮面试过关斩将,简直开了挂一般,跟面试官正面对线,丝毫不虚。听我一一道来。 第一轮 第一面是电话面试,晚上10点半。我特么一脸问号?你们这是刚加完班吧?事实上我