入职大厂,齐姐精选的 9 道 Java 集合面试题
Java 集合框架其实都讲过了,有一篇讲 Collection 的,有一篇讲 HashMap 的,那没有看过的小伙伴快去补下啦,文末也都有链接;看过的小伙伴,那本文就是检测学习成果的时候啦
今天这篇文章是单纯的从面试的角度出发,以回答面试题为线索,再把整个 Java 集合框架复习一遍,希望能帮助大家拿下面试。
先上图:

当面试官问问题时,我会先把问题归类,锁定这个知识点在我的知识体系中的位置,然后延展开来想这一块有哪些重点内容,面试官问这个是想考察什么、接下来还想问什么。
这样自己的思路不会混乱,还能预测面试官下一个问题,或者,也可以引导面试官问出你精心准备的问题,这场面试本质上就是你在主导、你在 show off 自己扎实的基础知识和良好的沟通交流能力。
其实我在 LRU 那篇文章里就说到过这个观点,然后就有读者问我,说会不会被面试官看穿?
答:看出来了又怎样?面试官阅人无数,是有可能看出来的,但是也只会莞尔一笑,觉得这个同学很用心。
精心准备面试既是对面试官个人时间的尊重,也是表明了你对这家公司的兴趣,这样的员工不是每家公司都想要的吗?
好了,进入正题,今天就来解决这 9 大面试题。
1. ArrayList vs LinkedList
这题的问法很多,比如
最简单的就直接问 ArrayList 和 LinkedList 的区别和联系; 或者问你什么时候要选择 ArrayList,什么时候选择 LinkedList; 或者在你们聊到某个场景、或者在算法题中,面试官问你如何选择。
万变不离其宗。
首先结论是:
绝大多数的情形下都偏向于用 ArrayList,除非你有明确的要使用LinkedList的理由。如果你不确定用哪个,就用 ArrayList。
两者在实现层面的区别是:
ArrayList是用一个可扩容的数组来实现的 (re-sizing array);LinkedList是用doubly-linked list来实现的。
而数组和链表之间最大的区别就是数组是可以随机访问的(random access)。
这个特点造成了在数组里可以通过下标用 O(1) 的时间拿到任何位置的数,而链表则做不到,只能从头开始逐个遍历。
两者在增删改查操作上的区别:
在「改查」这两个功能上,因为数组能够随机访问,所以 ArrayList 的效率高; 在「增删」这两个功能上,如果不考虑找到这个元素的时间,数组因为物理上的连续性,当要增删元素时,在尾部还好,但是其他地方就会导致后续元素都要移动,所以效率较低;而链表则可以轻松的断开和下一个元素的连接,直接插入新元素或者移除旧元素。
但是呢,实际上你不能不考虑找到元素的时间啊。。。虽然 LinkedList 可以 O(1) 的时间插入和删除元素,可以你得先找到地方啊!
不是有个例子么,修理这个零件只需要 1 美元,但是找到这个零件需要 9999 美元。我们平时修 bug 也是如此,重点是找到 root cause 的过程。
而且如果是在尾部操作,数据量大时 ArrayList 会更快的。
事实上,LinkedList 是很多性能问题的 bug,那么为什么呢?
因为 ListNode 在物理内存里的不连续,导致它用了很多小的内存片段,这会影响很多进程的性能以及 cache-locality(局部性);所以即便是理论上的时间复杂度和 ArrayList 一样时,也会导致实际上比 ArrayList 慢很多。
2. ArrayList vs Vector
答:
Vector是线程安全的,而ArrayList是线程不安全的;扩容时扩多少的区别,文邹邹的说法就是 data growth methods不同,Vector默认是扩大至 2 倍;ArrayList默认是扩大至 1.5 倍。
回顾下这张图,

Vector 和 ArrayList 一样,也是继承自 java.util.AbstractList,底层也是用数组来实现的。
但是现在已经被弃用了,因为它是线程安全的。任何好处都是有代价的,线程安全的代价就是效率低,在某些系统里很容易成为瓶颈,所以现在大家不再在数据结构的层面加 synchronized,而是把这个任务转移给我们程序员。
那怎么知道扩容扩多少的呢?
看源码:

这是 Vecotr 的扩容实现,因为通常并不定义 capacityIncrement,所以默认情况下它是扩容两倍。
VS

这是 ArrayList 的扩容实现,算术右移操作是把这个数的二进制往右移动一位,最左边补符号位,但是因为容量没有负数,所以还是补 0.
那右移一位的效果就是除以 2,那么定义的新容量就是原容量的 1.5 倍。
3. ArrayDeque vs LinkedList
首先要清楚它们之间的关系:

答:
ArrayDeque 是一个可扩容的数组,LinkedList 是链表结构; ArrayDeque 里不可以存 null 值,但是 LinkedList 可以; ArrayDeque 在操作头尾端的增删操作时更高效,但是 LinkedList 只有在当要移除中间某个元素且已经找到了这个元素后的移除才是 O(1) 的; ArrayDeque 在内存使用方面更高效。 所以,只要不是必须要存 null 值,就选择 ArrayDeque 吧!
那如果是一个很资深的面试官问你,什么情况下你要选择用 LinkedList 呢?
答:Java 6 以前。因为 ArrayDeque 在 Java 6 之后才有的。
为了版本兼容的问题,实际工作中我们不得不做一些妥协。
4. HashSet 实现原理
答:
HashSet 是基于 HashMap 来实现的,底层采用 Hashmap 的 key 来储存元素,主要特点是无序的,基本操作都是 O(1) 的时间复杂度,很快。
所以它的实现原理可以用 HashMap 的来解释。
5. HashMap 实现原理
答:
在 JDK1.6/1.7,数组 + 链表;在 JDK 1.8,数组 + 红黑树。
具体说来,
对于 HashMap 中的每个 key,首先通过 hash function 计算出一个哈希值,这个哈希值就代表了在桶里的编号,而“桶”实际上是通过数组来实现的,但是桶有可能比数组大呀,所以把这个哈希值模上数组的长度得到它在数组的 index,就这样把它放在了数组里。

这是理想情况下的 HashMap,但现实中,不同的元素可能会算出相同的哈希值,这就是哈希碰撞,即多个 key 对应了同一个桶。
为了解决哈希碰撞呢,Java 采用的是 Separate chaining 的解决方式,就是在碰撞的地方加个链子,也就是上文说的链表或者红黑树。
具体的 put() 和 get()这两个重要 API 的操作过程和原理,大家可以在公众号后台回复「HashMap」获取文章阅读。
6. HashMap vs HashTable
答:
Hashtable是线程安全的,HashMap并非线程安全;HashMap允许key中有null值,Hashtable是不允许的。这样的好处就是可以给一个默认值。
其实 HashMap 与 Hashtable 的关系,就像 ArrayList 与 Vector,以及 StringBuilder 与 StringBuffer。
Hashtable 是早期 JDK 提供的接口,HashMap 是新版的。这些新版的改进都是因为 Java 5.0 之后允许数据结构不考虑线程安全的问题,因为实际工作中我们发现没有必要在数据结构的层面上上锁,加锁和放锁在系统中是有开销的,内部锁有时候会成为程序的瓶颈。
所以 HashMap, ArrayList, StringBuilder 不再考虑线程安全的问题,性能提升了很多。
7. 为什么改 equals() 一定要改 hashCode()?
答:
首先基于一个假设:任何两个 object 的 hashCode 都是不同的。也就是 hash function 是有效的。
那么在这个条件下,有两个 object 是相等的,那如果不重写 hashCode(),算出来的哈希值都不一样,就会去到不同的 buckets 了,就迷失在茫茫人海中了,再也无法相认,就和 equals() 条件矛盾了,证毕。
hashCode()决定了key放在这个桶里的编号,也就是在数组里的index;equals()是用来比较两个object是否相同的。
8. 如何解决哈希冲突?
一般来说哈希冲突有两大类解决方式:
Separate chaining Open addressing
Java 中采用的是第一种 Separate chaining,即在发生碰撞的那个桶后面再加一条“链”来存储。

那么这个“链”使用的具体是什么数据结构,不同的版本稍有不同,上文也提到过了:
JDK1.6 和 1.7 是用链表存储的,这样如果碰撞很多的话,就变成了在链表上的查找,worst case 就是 O(n);
JDK 1.8 进行了优化,当链表长度较大时(超过 8),会采用红黑树来存储,这样大大提高了查找效率。
(话说,这个还真的喜欢考,已经在多次面试中被问过了,还有面试官问为什么是超过“8”才用红黑树
入职大厂,齐姐精选的 9 道 Java 集合面试题的更多相关文章
- 大厂必问的Java集合面试题
本文目录: 常见的集合有哪些? List .Set和Map 的区别 ArrayList 了解吗? ArrayList 的扩容机制? 怎么在遍历 ArrayList 时移除一个元素? Arraylist ...
- 精选30道Java多线程面试题
1.线程和进程的区别 进程是应用程序的执行实例.比如说,当你双击的Microsoft Word的图标,你就开始运行的Word的进程.线程是执行进程中的路径.另外,一个过程可以包含多个线程.启动Word ...
- [刘阳Java]_精选20道Java多线程面试题
1. 多线程使用的优缺点? 优点: (1)多线程技术使程序的响应速度更快 (2)当前没有进行处理的任务可以将处理器时间让给其它任务 (3)占用大量处理时间的任务可以定期将处理器时间让给其它任务 (4) ...
- 精选20道Java代码笔试题
1.运算符优先级问题,下面代码的结果是多少? public class Test { public static void main(String[] args) { int k = 0; int r ...
- 一线大厂面试官最喜欢问的15道Java多线程面试题
前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...
- 靠这些秋招秘笈,齐姐的学妹今年已经拿到了 8 个offer!
小齐说: 现在秋招进行时,正在找工作的小伙伴进度都怎么样了呀? 今天这篇文章是我武大的学妹今年秋招的经验分享,庆妹去年才决定转行,现在已手握 N+ 个 offer - 这篇文章干货满满,庆妹对每一块面 ...
- 我,35岁Android开发,高龄入职鹅厂,试用期未过被劝退......今年实惨
今天,笔者盘点.综合分享一位腾讯员工的"心声".这份心声中干货还是不少的,主要关于腾讯的一些职场生活--希望这些"干货"能对你有所帮助. 什么部门?给补偿吗? ...
- 新人入职100天,聊聊自己的经验&教训
这篇文章讲了什么? 如题,本屌入职100天之后的经验和教训,具体包含: 对开发的一点感悟. 对如何提问的一点见解. 对Google开发流程的吐槽. 如果你 打算去国外工作. 对Google的开发流程感 ...
- 初入职场的建议--摘自GameRes
又开始一年一度的校招了,最近跑了几个学校演讲,发现很多话用短短的一堂职业规划课讲还远远不够,因为那堂课仅仅可能帮大家多思考怎样找到一份合适的工作,并没有提醒大家怎样在工作中发展自己的职业. 见过这么多 ...
随机推荐
- 【Flutter 实战】各种各样形状的组件
老孟导读:Flutter中很多组件都有一个叫做shape的属性,类型是ShapeBorder,比如Button类.Card等组件,shape表示控件的形状,系统已经为我们提供了很多形状,对于没有此属性 ...
- 【CF】Sereja and Arcs
#include <bits/stdc++.h> #define llong long long using namespace std; const int N = 1e5; const ...
- 现象:当指定logback的FileNamePattern为日期2020-01-15后,如果有线程不断的往里写log,过了零点文件不会变成下一日2020-01-16,还是会在2020-01-15里继续写 结论:写log的线程不停,文件不会按日子更换。
logback版本:1.1.11 这个是我实验验证的,昨天我配置了一个logback,然后用两个线程不断往里写log,结果发现到了今天2020-01-16日,log文件还是昨天的logbackCfg. ...
- Spring JPA 查询创建
Spring JPA 查询创建 这是JPA内容的核心部分,可以收藏用作参阅文档. 1. 查询转化和关键字 例:一个JPA查询的转化 public interface UserRepository ex ...
- 5.AVStream和AVCodecParameters
AVStream和AVCodecParameters 说明: AVStream 结构表示当前媒体流的上下文,着重于所有媒体流共有的属性(并且是在程序运行时才能确定其值)和关联其他结构的字段. 其中co ...
- 安装paddle的问题,报错Can not find library: libcudnn.so. The process maybe hang.
今天在服务器上安装paddle的GPU版时报错 报错截图如下: 其实报错已经提示的很明显了,就是要添加一个环境变量.但我想到我之前并没有在全局环境下安装cudnn,以为是这个原因.因为之前安装pyto ...
- W5300中文手册
如果链接没了就Q我吧1178875532 链接:https://pan.baidu.com/s/1HcNJN_T6QJCvPWymU1sFDQ 提取码:suBB
- vue 实现页面跳转
首先,vue项目文件夹如下: components下有两个.vue文件,HelloWorld为创建时自动建立的,login需要自己创建的,login页面效果如下: 首先实现登录按钮的跳转,先对inde ...
- oracle数据处理之sql*loader(一)
SQL*Loader是oracle提供的可以从多种平面文件中向数据库中加载数据的工具,它比较适合业务分析类型数据库(数据仓库);使用sqlldr工具可以在很短的时间内向数据库中加载大量的数据,像把制作 ...
- [程序员代码面试指南]字符串问题-回文最少分割数(DP)
问题描述 给定一个字符串,输出把它全部切成回文子串的最小分割数. 例:str="ACDCDCDAD",输出2. 解题思路 DP 存储结构 dp数组dp[len+1],dp[i]表示 ...