md_files/自学/JAVA面试题.md

93 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## JAVA面试题1
### [说说 Java 中 HashMap 的原理?](https://www.mianshiya.com/bank/1860871861809897474/question/1834107117591187457)
![image-20250402170337830](https://pic.bitday.top/i/2025/04/02/s66t0w-0.png)
**为什么引入红黑树:**
当hash冲突较多的时候链表中的元素会增多插入、删除、查询的效率会变低退化成O(n)使用红黑树可以优化插入、删除、查询的效率logN级别。
转换时机:
链表上的元素个数大于等于8 且 数组长度大于等于64
链表上的元素个数小于等于6的时候红黑树退化成链表。
**链表插入方式变更:从"头插法"改为"尾插法"**
- **头插法特点**
- 插入时不需要遍历链表
- 直接替换头结点
- 扩容时会导致链表逆序
- 多线程环境下可能产生**死循环**
- **尾插法改进**
- 避免扩容时的链表逆序
- 解决多线程环境下的潜在死循环问题
### [Java 中 ConcurrentHashMap 1.7 和 1.8 之间有哪些区别?](https://www.mianshiya.com/bank/1860871861809897474/question/1780933294813114369)
![image-20250402170530218](https://pic.bitday.top/i/2025/04/02/s7ahq2-0.png)
![image-20250402170553033](https://pic.bitday.top/i/2025/04/02/s7f94s-0.png)
#### ConcurrentHashMap 不同JDK版本的实现对比
1. **数据结构**
- JDK1.7
- 使用 `Segment分段锁 + HashEntry数组 + 链表` 的数据结构
- JDK1.8及之后:
- 使用 `数组 + 链表/红黑树` 的数据结构与HashMap类似
2. **锁的类型与宽度**
- JDK1.7
- 分段锁(Segment)继承了 `ReentrantLock`
- Segment容量默认16不会扩容 → 默认支持16个线程并发访问
- JDK1.8
- 使用 `synchronized + CAS` 保证线程安全
- 空节点通过CAS添加**put操作**,多个线程可能同时想要将一个新的键值对插入到同一个桶中,这时它们会使用 CAS 来比较当前桶中的元素(或节点)是否已经被修改过。)
- 非空节点通过synchronized加锁**只锁住该桶**,其他桶可以并行访问。
3. **渐进式扩容JDK1.8+**
- **触发条件**:元素数量 ≥ `数组容量 × 负载因子(默认0.75)`
- **扩容过程**
1. 创建2倍大小的新数组
2. 线程操作数据时,逐步迁移旧数组数据到新数组
3. 使用 `transferIndex` 标记迁移进度
4. 直到旧数组数据完全迁移完成
### [500. 什么是 Java 的 CASCompare-And-Swap操作](https://www.mianshiya.com/question/1780933295027023873)
CAS操作包含三个基本操作数
1. **内存位置(V)**:要更新的变量
2. **预期原值(A)**:认为变量当前应该具有的值
3. **新值(B)**:想要更新为的值
CAS 工作原理:
1. 读取内存位置V的当前值为A
2. 计算新值B
3. 当且仅当V的值等于A时将V的值设置为B
4. 如果不等于A则操作失败(通常重试)
```text
伪代码表示:
if (V == A) {
V = B;
return true;
} else {
return false;
}
```