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

相关推荐
eggwyw8 分钟前
Anaconda安装卸载的详细流程指南
开发语言·python
Flynn Liang1 小时前
可观测性与成本治理:一次对话的 17 个观测点
java·langchain·可观测性·micrometer·langchain4j·token 成本·llm 监控
金銀銅鐵2 小时前
带您看懂字节码指令(三):同一行加法,为什么有四种指令
java·jvm
another heaven4 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
文丑颜不良啊6 小时前
LeetCode2821~2840题目解析
java·leetcode
SomeOtherTime6 小时前
Rust 闭包语法和原理(AI回答)
开发语言·后端·rust
apcipot_rain6 小时前
C++转Java日记(10)
java·开发语言
总要学点什么7 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
简 洁 冬冬7 小时前
泛型方法写法全面辨析:从「能编译」到「能跑」到「能用」
java·泛型
LGL6030A7 小时前
Java学习历程31——初识Spring Boot
java·spring boot·学习