java集合篇面试模拟

问题

1 Arraylist和LinkedList的区别,它们是有序的还是无序的

2 ArrayList 和 LinkedList 的应用场景?

3.ArrayList的扩容机制说一下

****4.****HashMap实现原理介绍一下?

5.HashMap是线程安全的吗?

6.在 Java 的 hashmap 中 get一个元素的过程是怎样的?

7.hashmap的put过程介绍一下

8.HashMap的扩容机制介绍一下

9.ConcurrentHashMap怎么实现的?

10.说一下HashMap和Hashtable、ConcurrentMap的区别

11.Set集合有什么特点?如何实现key无重复的

回答

1

**底层数据结构不同:**ArrayList 是数组实现,LinkedList 是链表实现

**插入和删除操作的效率不同:**ArrayList 在尾部进行插入和删除操作时效率较高,在中间或开头插入、删除效率很低,需要移动后面的所有元素;

LinkedList 在头部和尾部进行插入、删除操作时效率很高,只需要调整节点的指针即可,

在中间位置操作,需要遍历链表找到目标位置,时间复杂度是 O (n),后续只需要调节指针

**随机访问的效率不同:**ArrayList 通过索引快速访问元素,时间复杂度为 O (1),LinkedList必须从头或尾逐个遍历查询,时间复杂度为O (n)

**空间占用:**LinkedList每个元素比ArrayList多两个指针,存储元素数量相同时,LinkedList占用更大

都是有序的

2

ArrayList适用于需要频繁访问的场景。LinkedList适用于频繁进行插入和删除操作的场景。

3.

ArrayList在添加元素时,如果当前元素个数已经达到了内部数组的容量上限,就会触发扩容操作。先算新容量,默认是原来的 1.5 倍,用移位运算效率更高;

扩容操作涉及创建新数组、复制旧元素、把引用指向新数组。

4.

JDK 7 是「数组 + 链表」 通过哈希算法将元素的键(Key)映射到数组中的槽位。采用头插法,多线程下会成环导致 get 死循环

JDK 8 改成「数组 + 链表 + 红黑树」 ------链表长度 ≥ 8 且 数组长度 ≥ 64 时转红黑树,查找从 O(n) 降到 O(log n);树节点 ≤ 6 时退化回链表。采用尾插法,扩容按 hash & oldCap 拆成高低两条链整体搬走, 不会成环,但仍会覆盖丢数据

5.

JDK 8解决了 并发扩容时可能形成环形链表的问题,并没有解决多线程操作 HashMap 时的数据丢失问题

解决方法是 优先使用 ConcurrentHashMap

6.

get 就三步:

先 hash(key) 定位桶;桶空直接返回 null;

桶不空先比首节点(最快路径),命中就返回;没命中看类型------是树就走 getTreeNode 按 hash 分叉 O(log n),是链表就 do-while 逐个比 hash 和 equals,最长也就 8 个节点;找不到统一返回 null。全程不改 modCount,key 为 null 时 hash 是 0,落 0 号桶。

7.

put()方法用于向HashMap中添加键值对

1.拿到 key,计算它的 hash 值,通过 hash 值定位到数组对应的桶下标。

2.桶为空,创建一个新的 Node 对象来存储键值对

桶不为空,先判断头节点 key 是否一致,一致就覆盖 value。不一致就遍历链表或者红黑树,找到相同 key 就更新,找不到就插入新节点。

3.插入后如果链表长度到 8、数组≥64,链表转红黑树。

4.判断负载因子是否超过扩容阈值,超过就扩容为原来 2 倍,重新迁移节点。

8.

默认的负载因子是0.75,即如果hashmap中的元素个数超过了总容量75%,则会触发扩容

扩容做两件事 :新建 2 倍数组 → 搬移旧数据。

搬移的巧妙处 :因为容量是 2 的幂,(n-1) 的掩码扩容后高位只多 1 bit ,所以只需判断 e.hash & oldCap:为 0 留在原位,非 0 移到「原位 + oldCap」,无需重算 hash。

9.

JDK 1.7 :是Segment分段锁

JDK 8 :和 HashMap 一样的 数组 + 链表/红黑树 ,用 volatile+ CAS + synchronized 保证安全,锁粒度细化到单个桶 。

写入四步:

容器是否为空,为空则使用 volatile 加 CAS 来初始化

桶空用 CAS 无锁写入

桶非空 synchronized 锁住桶头节点再遍历覆盖/尾插

插入完成后更新计数。

读操作全程无锁 ------靠 volatile(Java 的关键字,用来修饰变量 ) 保证可见性,这是它读性能高的根本原因。

10.

HashMap:线程不安全,允许 null,初始容量 16,2 倍扩容,数组 + 链表 + 红黑树。 Hashtable:全局 synchronized 锁,并发差,不允许 null,初始容量 11,扩容 2n+1,只有数组 + 链表,基本淘汰。 ConcurrentHashMap:线程安全,不允许 null。1.7 分段锁;1.8 去掉分段锁,CAS + 桶级 synchronized,并发性能更好。

11.

set集合特点:Set集合中的元素是唯一的,不会出现重复的元素。

HashSet / LinkedHashSet :底层是哈希表,插入元素时先用 hashCode() 定位桶,再用 equals() 比较是否已存在相同元素,存在则不再插入;

TreeSet :底层是红黑树,插入元素时不调用 hashCode/equals,而是用自然排序或自定义 的返回值是否为 0 来判断是否重复。

相关推荐
不是万能的豆学长3 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
时间静止不是简史3 小时前
生产事故排查:Redis 宕机导致补偿队列消费线程死亡,通话录音未上送业务平台
java·redis
2301_32241428047 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
懂点Tech8 小时前
ctfshow MISC入门图片篇(信息附加):misc41解题思路
开发语言·python
怕浪猫8 小时前
外包和大厂的前端代码,差在凌晨三点
前端·面试·github
金銀銅鐵9 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
catchadmin9 小时前
PHP 8.7 协程新提案 让跨协程代码共享请求身份
开发语言·php
福建佰胜张工9 小时前
SMC 薄型气爪 MHF2-16D1 深度解析:平行开闭、低剖面结构在自动化装配中的选型与落地
java·服务器·安全·自动化
念何架构之路9 小时前
go-grpc设计思想
开发语言·后端·golang
catoop9 小时前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全