2026-10-23 12:10:34
元保数科Java面试核心问题及解答要点如下:
一、算法与数据结构快速排序算法及优化
原理:分治思想,通过选取基准值将数组分为左右两部分,递归排序。
低效场景:
数组已有序或逆序时,每次划分极度不平衡,时间复杂度退化为O(n2)。
大量重复元素时,效率降低。
优化方法:
随机化选择基准值(避免最坏情况)。
三数取中法(选首、中、尾的中位数作为基准)。
对小规模子数组切换插入排序(减少递归开销)。
HashMap扩容机制
JDK版本:常见为JDK 8及以上(面试中需明确版本)。
添加键值对过程:
计算键的哈希值,定位桶索引。
若桶为空,直接插入;否则遍历链表或红黑树。
插入后检查是否需扩容(元素数 > 负载因子×容量)。
扩容两倍原因:
减少哈希冲突(新容量为旧容量的2倍,重新哈希后元素分布更均匀)。
位运算优化(n << 1比乘法更快)。
链表转红黑树的阈值
JDK 8中阈值为8:当链表长度超过8时,转换为红黑树以降低查询复杂度(从O(n)到O(log n))。
设计考量:
哈希冲突较小时,链表更节省内存。
冲突严重时,红黑树提升性能。
MySQL索引结构
B+树:默认索引结构,支持范围查询和排序,磁盘IO效率高。
其他索引:
哈希索引:仅支持等值查询(如Memory引擎)。
全文索引:用于文本搜索(如InnoDB的FULLTEXT)。
R-Tree:空间索引(用于地理数据)。
事务隔离级别与幻读
隔离级别(由低到高):
读未提交(Read Uncommitted):可能脏读。
读已提交(Read Committed):避免脏读,但不可重复读。
可重复读(Repeatable Read,MySQL默认):避免不可重复读,但可能幻读。
串行化(Serializable):完全隔离,性能最低。
幻读产生场景:
在可重复读级别下,同一事务内两次查询结果集不同(如其他事务插入新数据)。
间隙锁(Gap Lock):
InnoDB通过间隙锁锁定索引记录之间的间隙,防止幻读(仅适用于可重复读级别)。
乐观锁与ABA问题
乐观锁:通过版本号或CAS(Compare-And-Swap)实现,假设冲突较少,更新时检查版本是否被修改。
ABA问题:
现象:值从A→B→A,CAS误认为未被修改。
解决方案:添加版本号或时间戳(如Java的AtomicStampedReference)。
应用场景:超卖问题(如库存扣减)。
分布式锁实现
常见方法:
Redis的SETNX(需设置过期时间,避免死锁)。
Redlock算法(多Redis实例协同)。
ZooKeeper临时顺序节点。
一人一单问题流程:
尝试获取锁(如SETNX key value NX PX 30000)。
执行业务逻辑(如扣减库存)。
释放锁(删除键或自动过期)。
问题与解决:
锁超时释放:通过唯一标识(如UUID)判断锁归属,避免误删他人锁。
锁续期:如Redisson的看门狗机制。
Redis内存淘汰策略
主动淘汰:
volatile-lru:淘汰最近最少使用的过期键。
allkeys-lru:淘汰所有键中最近最少使用的。
volatile-ttl:淘汰即将过期的键。
被动淘汰:访问键时发现内存不足时触发。
线程池使用与注意事项
核心参数:
核心线程数、最大线程数、任务队列、拒绝策略。
任务处理流程:
核心线程未满时,直接创建线程执行。
核心线程满时,任务进入队列。
队列满时,创建非核心线程(直至最大线程数)。
线程数达上限且队列满时,触发拒绝策略(如AbortPolicy抛异常)。
注意事项:
避免任务堆积导致OOM(合理设置队列大小)。
监控线程池状态(如ActiveCount、QueueSize)。
线程间通信与同步
机制:
wait/notify:基于对象锁,需在同步块中使用。
CountDownLatch:等待多个线程完成。
CyclicBarrier:线程到达屏障后阻塞,待全部到达后继续执行。
wait/notify场景:生产者-消费者模型、任务调度。
示例:聚焦后端开发,深耕高并发、分布式系统领域,结合业务场景优化技术方案。
技术能力:熟悉Java核心(如JVM、并发)、分布式框架(如Spring Cloud)、数据库优化。
学习能力:快速掌握新业务(如通过文档、源码分析)。
示例:研究生阶段深入网络安全,掌握加密协议、渗透测试等技能,提升系统安全设计能力。