最近看到Java相关的面试时,看到一篇关于HashMap的相关面试知识点,感觉蛮好的!现在的面试点不会围绕某个知识让面试者去详细阐述,而会通过一些系列的相关问题去让你阐述,进而形成从点到线,再由线到面来考察面试者的基本功和发散性思维。无穷无尽地深入,知道你回答不出来或者面试官问到底!

面试官:1、你了解/使用过HashMap吗?为什么是使用HashMap?

这个问题相信你一定可以或多或少的回答出来一些相关知识,比如一些特性(优点)!这仅仅是一个考察你对HashMap的前奏!

比如:

  1. HashMap是一个散列桶(直观的说出来HashMap的数据结构特性:数组和链表),存储的是key-value(键值对)映射
  2. HashMap采用了数组和链表节后的数据结构,能在查询和修改便于继承了数组的线性查找和链表的寻址修改提高效率
  3. HashMap是非安全的(非synchronized),所以不保证安全的情况下,速度很快
  4. HashMap可以是key和value都是null,而Hashtable则不能(原因是Hashtable使用equal方法会产生空指针异常,而HashMap经过API处理过的,不会出现在这种情况)
  5. 等等

回答到这儿,相信面试官已经知道你了解和使用过HashMap,但面试官会急转之下,深入问道一些刁钻或你对此比较模糊认识的问题,比如一些具体详细的问题

面试官:2、你知道HashMap的工作原理吗?你知道HashMap的put、get方法工作原理吗?

!!??我去!一脸懵!或许你使用HashMap非常的666,但工作原理?艾玛!真的没有深入研究吧!如果你真的不知道的话,也就意味着这个话题终结,但你说一些错误的问题,那就很危险了!面试就是,知道的说,不知道的就直接说不知道,态度很重要!!

来吧,看看这个问题考察的东西吧!

就第一个问题来说:

HashMap是基于hashing的原理!使用HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。

到此,你已经回答出来的HashMap的工作原理,但是(关键指出,HashMap是在backet中存储键和值对象,作为Map的节点Map.Entry),这个有利于你对应get方法获取对象的工作原理,如果你没有意识到这一点的话,或许不仅仅认为只在backet中存储值的话,你就无法回答是如何获取对象的。

简化模拟一下数据结构

Node[] table = new Node[16];    //散列桶初始化,table// 节点数据结构
class Node{int hash;    // hash值key;         // 键value;       // 值Node next;   // 用于指向链表的下一层(产生冲突,使用拉链法)
}

就第二个问题来说:

put源码

public V put(K key, V value) {return putVal(hash(key), key, value, false, true);
}

put过程大致可以分为一下阶段(针对常用的jdk1.8)

  1. 对key值进行Hash值计算(hash方法),然后再在计算下标
  2. 如果key对象没有在backet中存在,则直接放在桶中存储(也称之为碰撞)
  3. 如果key对象存在,则会以链表的方式存储链接在后面
  4. 如果链表的长度超过了阈值(TREEIFY THRESHOLD==8),就会把链表转换为红黑树,链表长度低于6,就把红黑树转换为链表
  5. 如果节点存在,就会替换旧值
  6. 如果桶满(容量16*加载因子0.75),就会resize(扩容2倍重排)

get源码

public V get(Object key) {Node<K,V> e;return (e = getNode(hash(key), key)) == null ? null : e.value;
}

get获取对象的工作原理

上面已经对于put方法,那对于get方法就简单了很多

当我们调用get方法时,HashMap会使用键对象的hashcode找到bucket的位置,找到bucket位置后,会调用keys.equal()方法去找到链表中正确节点,最终找到值对象

或许以上仅仅是HashMap故事的开始,面试官会在日常开发中遇到的问题来深入询问你的掌握程度。

面试官:3、当两个对象的hashcode相同会发生什么?

看到这个问题的第一反应该是:我去,又是一脸懵!!

从这里开始,真正的困惑开始了,一些面试者会回答因为hashcode相同,所以两个对象是相等的,HashMap将会抛出异常,或者不会存储它们等等,各种答案,五花八门!然后面试官可能会提醒你hashcode和equal两个方法,也有可能有些面试者会直接放弃面试,当然这样关于HashMap的问题就此结束的。

当然会有一些优秀的面试者会继续前进:如果hashcode相等,则可以判断他们的bucket位置相同,会产生“碰撞”,因为HashMap使用链表存储对象,这个Entry(包含键值对的Map.Entry对象)会存储链表。这个答案是在点的,也非常合理。虽然有很多处理碰撞的方法,但这种方法是最简单的,也真是处理HashMap的方法。

但是,故事好没有结束,问题还会继续。哥们儿!挺住....、

面试官:4、如果两个键的hashcode相同,你会如何获取值对象?

当然,获取Map的值对象肯定是通过get方法,那就围绕着get方法工作原理就坡下驴吧!但是,着是不够的呦!这也不是面试官想要的答案,要不然这个问题也不会出现的(上面已经问过你了!!)。

面试者:当我们调用get方法时,HashMap会使用键对象的hashcode值找到bucket位置,然后获取值对象。

面试官:如果有两个或者多个bucket在同一个位置呢?

面试者:HashMap会遍历链表,直到找到对应的值对象。

面试官:你并没有值对象去比较,你是如何确定确定找到值对象的?(除非面试者直到HashMap在链表中存储的是键值对,否则他们不可能回答出这一题。)

还记得HashMap是在backet中存储键和值对象,作为Map的节点Map.Entry吗?那问题就简单化了

面试者:找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。(完美的答案!)

许多情况下,面试者会在这个环节中出错,因为他们混淆了hashCode()和equals()方法。因为在此之前hashCode()屡屡出现,而equals()方法仅仅在获取值对象的时候才出现。一些优秀的开发者会指出使用不可变的、声明作final的对象,并且采用合适的equals()和hashCode()方法的话,将会减少碰撞的发生,提高效率。不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度,使用String,Interger这样的wrapper类作为键是非常好的选择。

如果你认为到这里已经完结了,那么听到下面这个问题的时候,你会崩溃或者开始紧张了。

面试官:5、如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?

除非你真的了解HashMap的工作原理,否则你是回答不出来的......

同时,问到这个问题之后,要及时的意识到面试官要把你往线程安全的方向引入了,做好准备。

你可以这样回答:

当数据过大时候,Map则会进行一次rehashing。

默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时,和其他集合类(如Array等)一样,将会创建原来HashMap大小2倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程及时rehashing,毕竟在这个过程中调用hash方法找到了新的bucket位置

回答道现在,面试官还不会放过i的,接着会问你。

面试官:6、你了解重新调整HashMap大小存在什么问题吗?

这个问题往往是在多线程的情况下,当然你需要了解条件竞争,要不然,你还是无法找到切入点。

当调整map大小,会产生条件竞争,因为在多线程条件下,两个线程都发现HashMap需要调整大小,那么就会同时尝试调整,在调整的过程中,存储在LinkedList中的元素次序会进行倒叙排列(因为移动到新的bucket位置时候,HashMap会将元素放在LinkedList的头部,而不是尾部,为了尾部遍历)。一旦条件竞争发生了,就会出现死循环。

问题一步步的引导,你回答的越多,则代表掌握的东西越多,这是必然!

那问题由来了,面试官还会继续问你的!

面试官:7、为什么多线程会导致死循环,它是怎么发生的?

怎么样!?面试官会根据你的回答,一步步引导下去,如果你真的知道上一个问题的答案,那吗对于下一个问题也就不用太担心;相反,当你是蒙的,那就会被面试官一步步的识破,最后的结果会很尴尬的!所以,还是那个原则,不懂的话,直接跳过,不要瞎说哦!

对于这个问题的突破口就是出现死循环的根源是什么?很大程度死循环的产生是数据结构的设置,以及对跟数据的操作不当引起的。那么,HashMap的数据结构你应该很了解了吧!没错,就是数组+链表(JDK8后是数组+链表+红黑树了)!数组?线性结构,无论如何是不会产生死循环的!那就剩下链表了(链表很容易产生回路的)!对!就是他!链表也正是HashMap处理碰撞的方式。

HashMap的容量是有限的。当经过多次元素插入时,使得HashMap达到一定的饱和度(接近加载因子0.75),Key映射位置发生冲突的几率会逐渐提高。这时候,HashMap需要扩展他的长度,也就是进行resize(扩容)。

(当然,这时候你可以范文面试官:很奇怪了,为什么在多线程下使用HashMap呢?嘿嘿嘿,面是过程中不仅仅是面试官问你,同样在不合理情况下,你也可以反问面试官,这样会让面试官感到你独特的一面,所谓艺高人胆大嘛!)

面试官:8、如果我想使用HashMap实现多线程,可以做到吗?

哈哈哈!这个时候估计是面试官对你的质问的一个变相的回应!这个会考察多线程下的HashMap,方法很多比如,加锁(极度不推荐使用,但是可以回答)、使用Collections中的方法封装,也可以使用其他拥有相同效果的类代替等等。

当然可以的。可以使用java.util.Collections.synchronizedMap(Map)的方式进行处理。(这是最简单,最有效的的回答,面试官找不到破绽,即便你知道ConcurrentHashMap等方式)简单回答就行了,至于其他问题,再作回答就好了,要懂得适时的收敛,你懂的!!

哈哈哈!经过一系列的问题,你是不是可以理解面试的方式,其实是一种综合问题的分析,不仅仅是深度,还有广度!所以,小伙伴们,功夫应用在平时,到时候不至于手忙脚乱!

---------------------
作者:编码世界
来源:CSDN
原文:https://blog.csdn.net/dgxin_605/article/details/86249771
版权声明:本文为博主原创文章,转载请附上博文链接!!

Java面试系列--HashMap相关推荐

  1. Java面试系列之并发编程专题-Java线程池灵魂拷问

    金三银四跳槽季即将来临,想必有些猿友已经蠢蠢欲动在做相关的准备了!在接下来的日子里,笔者将坚持写作.分享Java工程师在面试求职期间的方方面面,包括简历制作.面试场景复现.面试题解答.谈薪技巧 以及 ...

  2. JAVA面试系列(二)消息中间件

    本人目前项目中有用到rocketMQ作为数据传输过程中的中间件,今天整理了一下资料,记录一下自己对消息中间件的理解. 一.概念 1.MQ message queue消息队列,消息队列是就是队列,是一种 ...

  3. java面试之HashMap延伸出来的--什么是ConcurrentHashMap?

    1.HashMap是线程安全的吗? 2 2答–ConcurrentHashMap 3 要学习多线程编程的话,ConcurrentHashMap的源码拿来阅读一下,不失为一个好的学习方法. Segmen ...

  4. Java集合系列---HashMap源码解析(超详细)

    1 HashMap 1)特性: 底层数据结构是数组+链表+红黑树运行null键和null值,,非线程安全,不保证有序,插入和读取顺序不保证一致,不保证有序,在扩容时,元素的顺序会被重新打乱 实现原理: ...

  5. 搞定java面试系列--jvm3 gc垃圾回收

    1.明确什么是垃圾 答案:在进行gc操作时候没有存活的对象. 那么怎么去判断对象是否存活: 老的方式-引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回 ...

  6. JAVA面试系列:你了解系统可用性吗?

    文章目录 1.背景 1.1.可用性 1.2.衡量可用性 1.3.不可用原因 2.解答 2.1.拆分 2.1.1.水平拆分 2.1.2.垂直拆分 2.1.3.读写分离 2.2.降级 2.2.1.限流 2 ...

  7. Java面试系列——数据库(01)数据库的作用、分类、SQL语言、运算符

    数据库作为组织.存储和管理数据的仓库,在后端开发中扮演着不可或缺的角色,前面已经讲了Java基础篇的一些面试题,现在开始数据库篇,主要以Mysql和Redis作为讲解的重点,这两种数据库也是关系型数据 ...

  8. Java面试系列-MongoDB

    什么是MongoDB?为什么使用MongoDB? MongoDB是面向文档的NoSQL数据库,用于大量数据存储.MongoDB是一个在2000年代中期问世的数据库.属于NoSQL数据库的类别.以下是一 ...

  9. 【Java面试系列】GateWay异步非阻塞模型

    GateWay工作流程 核心流程图如下: 核心概念 客户端向 SpringCloud GateWay 发出请求,如果 GateWay Handler Mapping 确定请求与路由匹配,则将其发送到 ...

最新文章

  1. performActionForShortcutItem方法未触发
  2. eclipse中的maven build、maven clean、maven install和maven test的区别
  3. Tomcat9.0 设置局域网内其他电脑或手机端访问{9.0更新}
  4. 无锡c语言编程培训学校,无锡c语言培训班——C语言基础知识
  5. 一道面试题:猫大叫了一声...
  6. 吃货阶段02 商品类的定义 需求 0925
  7. 倒计时6天|2020腾讯广告犀牛鸟计划申请即将截止,错过再等一年!
  8. mySql 修改字段名
  9. Mapv 是地理信息可视化开源库
  10. SiteMesh详解
  11. oracle-rac实例不能启动 报ORA-03113
  12. 《博弈论全家桶》(ACM / OI)(超全的博弈论 / 组合游戏大合集)
  13. Collectors.toMap报错 :Duplicate key
  14. 极光推送 简书android,极光推送 (具体步骤,指导操作,推送成功)
  15. 话说嵌入式软件工程师的工资待遇
  16. Android Studio开发手机APP(二)-利用MQTT通信开发物联网程序
  17. 各种智能跟随定位技术解剖
  18. 腾讯云数据库开源再突破:TDSQL PG版查询性能提升百倍
  19. Pikachu(皮卡丘)靶场搭建
  20. 【软件安全:软件安全技术课后习题及答案】

热门文章

  1. macbook重装系统 选择方案_超详细的mac重装系统教程
  2. 一个10年符号主义学者的深度讨论:如何理性看待ChatGPT?
  3. python爬取东方财富网资金流向数据(在本地生成csv文件)
  4. [摘记]数值方法02——内插法和外推法
  5. python网页转PDF
  6. 【IDEA】IDEA常用配置
  7. CalendarPicker
  8. DSP CCS12.00 芯片:TMS320F28335 结课设计 频率测量系统设计
  9. java计算机毕业设计水果商城源代码+数据库+系统+lw文档
  10. 【机器学习】阿里云天池竞赛——工业蒸汽量预测(1)