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 来判断是否重复。

相关推荐
Yyyyyy~1 小时前
【java】数组的定义和使用
java
niucloud-admin1 小时前
JAVA V6 多商户商城 开发文档——插件开发规范
java·开发语言
嘟哩DuliDuli1 小时前
创作 Agent 的任务状态该如何保存
android·java·javascript
wdfk_prog1 小时前
lely-canopen-rtt:为什么推荐在 RT-Thread 上使用 Lely CANopen 构建主站
java·运维·缓存·docker·容器
海盗12341 小时前
DSH 接入 OpenCode Go 报 400 MissingSessionID:从 LLM 语义层退到 fetch 传输层的完整排障
开发语言·后端·golang
Token掘金室1 小时前
JSON模式结构化输出报错
java·服务器·json
weixin199701080161 小时前
《Mercari OTA 直连接入:日本二手电商出海的API通道与600次/分钟限流实战》(附Python源码)
开发语言·数据库·python
秋饼1 小时前
Spring AI 2.0 接入 DeepSeek V4.1 Flash 生产级实战
java·ai·技术分享·后端开发
IT枫斗者枫哥1 小时前
Java 分批导出仍然 OOM?用 32 MiB 堆复现三种 CSV 写法
java