Java 30 组高频技术 / 知识点多角度对比

覆盖基础、集合、并发、流、JVM、框架、新特性,每组多维度详细区分

1. ArrayList vs LinkedList

对比维度:底层结构、查询、头尾增删、中间插入、内存开销、遍历、适用场景

  1. 底层:ArrayList 动态数组;LinkedList 双向链表
  2. 查询随机下标:ArrayList O (1),直接寻址;LinkedList O (n),需遍历节点
  3. 尾部新增:ArrayList 扩容时复制数组,平均快;LinkedList 仅修改指针,无扩容
  4. 中间 / 头部插入删除:ArrayList 需要数组后移,性能差;LinkedList 只改前后指针,速度快
  5. 内存:ArrayList 连续内存,缓存友好;LinkedList 每个节点存 prev/next,额外内存开销大
  6. 遍历:ArrayList fori/foreach 更快;LinkedList 仅 foreach 友好,fori 巨慢
  7. 场景:ArrayList 绝大多数业务(查询多、尾部新增);LinkedList 频繁头尾增删、实现队列 / 栈

2. HashMap vs ConcurrentHashMap(JDK8)

维度:线程安全、锁机制、并发性能、扩容、null 键值、数据结构

  1. 线程安全:HashMap 不安全,并发丢数据、死循环;CHM 线程安全
  2. 锁:HashMap 无锁;CHM CAS + synchronized 锁住链表 / 红黑树头节点,粒度细
  3. null:HashMap 允许 1 个 null key、多个 null value;CHM key/value 都不允许 null
  4. 扩容:HashMap 并发扩容链表死循环;CHM 分段迁移,并发扩容安全
  5. 结构:数组 + 链表 + 红黑树;同 HashMap 结构,增加并发控制
  6. 性能:单线程 HashMap 更快;多线程 CHM 远优于 Collections.synchronizedMap

3. HashMap vs TreeMap vs LinkedHashMap

维度:有序性、底层、查询速度、排序规则、使用场景

  1. HashMap:无序,哈希表,O (1),无排序;普通键值存储
  2. LinkedHashMap:插入 / 访问有序,哈希表 + 双向链表,O (1);有序遍历、简易 LRU 缓存
  3. TreeMap:key 升序,红黑树,O (logn);需要按 key 自然排序场景

4. ArrayList vs CopyOnWriteArrayList

维度:线程安全、读写性能、内存、迭代、适用场景

  1. 安全:ArrayList 不安全;COWAL 线程安全
  2. 读:COWAL 无锁,读取极快;ArrayList 单线程读快
  3. 写:COWAL 写入复制完整新数组,开销极大;ArrayList 写轻量
  4. 迭代:COWAL 迭代快照,无并发修改异常;ArrayList 遍历修改抛异常
  5. 场景:COWAL 读多写少(配置缓存);ArrayList 单线程操作

5. synchronized vs Lock(ReentrantLock)

维度:底层、锁粒度、公平锁、中断、超时、可重入、释放、性能

  1. 底层:synchronized JVM 底层实现;Lock API 层面,AQS 队列
  2. 公平锁:synchronized 仅非公平;Lock 支持公平 / 非公平切换
  3. 中断等待:synchronized 阻塞不可中断;lockInterruptibly () 可中断
  4. 限时等待:synchronized 无限阻塞;tryLock (time) 超时自动放弃
  5. 释放:synchronized 自动释放;Lock 必须 finally 手动 unlock,否则死锁
  6. 条件变量:synchronized 只能 1 个 wait;Lock 支持多个 Condition
  7. 性能:低竞争 synchronized 优化后接近 Lock;高并发 Lock 性能更好

6. volatile vs synchronized

维度:作用、原子性、可见性、重排、锁、使用场景

  1. volatile:仅保证可见性、禁止指令重排;不保证原子性,无锁
  2. synchronized:可见性 + 原子性 + 禁止重排,独占锁
  3. 计数场景:volatile i++ 并发错乱;synchronized 自增安全
  4. 开销:volatile 轻量;synchronized 存在阻塞、上下文切换
  5. 场景:volatile 状态标记、双重检查锁单例;synchronized 复合操作并发保护

7. Runnable vs Callable

维度:返回值、异常、线程池、run 方法、Future

  1. Runnable run () 无返回值,不能抛出受检异常;Callable call () 有返回值,可抛异常
  2. 线程池提交:submit (Runnable) 无返回;submit (Callable) 返回 Future 获取结果
  3. 异常:Runnable 异常只能内部捕获;Callable 异常可通过 Future.get () 捕获
  4. 配合:Runnable 基础线程;Callable 异步需要获取执行结果场景

8. CountDownLatch vs CyclicBarrier

维度:复用、计数归 0 逻辑、使用场景

  1. CountDownLatch:一次性,主线程等多个子任务完成;计数归零不可重置
  2. CyclicBarrier:可循环复用,多个线程互相等待全部到达屏障再一起执行
  3. 举例:CDL 主线程等待批量查询全部完成;CB 多分段计算,全部算完合并结果

9. 并行流 parallelStream vs 自定义线程池 CompletableFuture

维度:线程池、IO 阻塞、线程隔离、控制、异常

  1. parallelStream:共用全局 ForkJoinPool,无隔离;IO 阻塞拖垮全局所有并行流
  2. CompletableFuture:可传入自定义线程池,任务隔离,不影响其他业务
  3. 控制力度:并行流无法自定义线程数;线程池可自定义核心、最大线程
  4. 适用:parallelStream 纯内存计算;CompletableFuture IO、RPC、隔离异步任务

10. Stream 中间操作 vs 终止操作

维度:执行时机、返回值、是否消费流、作用

  1. 中间操作 (filter/map/sorted/peek):惰性执行,返回新 Stream,不消费流,仅构建执行链
  2. 终止操作 (collect/forEach/count/findFirst):触发实际计算,消耗流,无 Stream 返回
  3. 关键:无终止操作,中间代码完全不执行;流只能执行一次终止操作

11. map() vs flatMap()

维度:返回类型、嵌套集合、使用场景

  1. map:T -> R,一对一转换,返回 Stream<R>;嵌套 List 会变成 Stream<List<T>>
  2. flatMap:T -> Stream<R>,扁平化,拆解嵌套集合,输出单层流
  3. 场景:简单字段映射用 map;集合嵌套拆解用 flatMap

12. orElse() vs orElseGet()

维度:执行时机、性能、参数类型

  1. orElse (T obj):无论 Optional 是否为空,入参对象 / 方法一定会执行;适合轻量常量
  2. orElseGet (Supplier):仅空值时才执行 Supplier;适合耗时查询、IO 操作
  3. 性能:耗时逻辑优先 orElseGet,避免无用计算

13. Optional.of() vs Optional.ofNullable()

维度:入参 null 处理、使用场景

  1. Optional.of (obj):obj 为 null 直接抛出 NPE;确定对象非空时使用
  2. Optional.ofNullable (obj):obj 为 null 返回 Optional.empty ();不确定对象是否为空通用

14. String + 拼接 vs StringBuilder vs StringBuffer

维度:线程安全、性能、适用场景

  1. String +:编译期少量拼接会优化 StringBuilder;循环大量拼接生成大量中间对象,性能极差
  2. StringBuilder:非线程安全,单线程高性能;日常循环字符串拼接首选
  3. StringBuffer:加 synchronized,线程安全,性能更低;极少多线程拼接场景使用

15. == vs equals()

维度:比较内容、对象 / 基本类型、重写规则

  1. ==:基本类型比较值;引用类型比较内存地址
  2. equals ():Object 默认同 ==;String、包装类重写为比较内容;自定义实体需手动重写 equals+hashCode 才能按业务字段对比

16. 基本数据类型 vs 包装类

维度:存储位置、默认值、null、装箱拆箱、缓存

  1. 基本类型:栈内存,有默认值,不能为 null,无对象头,开销小
  2. 包装类:堆对象,默认 null,自动装箱 valueOf、拆箱 xxxValue;-128~127 缓存,超出 == 失效

17. final 修饰变量 / 方法 / 类 三者对比

  1. final 变量:基本类型值不可改;引用类型地址不可改,内部属性可修改
  2. final 方法:不可被子类重写,运行期避免动态绑定,小幅优化
  3. final 类:禁止继承,所有方法隐式 final,如 String、Integer

18. 接口 (Interface JDK8+) vs 抽象类 abstract class

维度:构造方法、成员变量、多继承、方法、构造、静态代码块

  1. 抽象类:有构造方法,成员变量可任意修饰,单继承,可实例变量、代码块
  2. 接口:无构造,变量默认 public static final,可多实现;JDK8 default/static 方法、JDK9 私有方法;仅行为契约,无状态

19. 重载 Overload vs 重写 Override

维度:位置、方法名、参数、返回值、权限、异常

  1. 重载:同类,同名,参数列表不同;返回值无要求;任意权限
  2. 重写:父子类,同名同参数同返回;子类权限不能更严格;受检异常不能抛出更宽泛

20. try-with-resources vs 手动 close ()

维度:关闭时机、异常、代码冗余、泄漏风险

  1. try-with-resources:实现 AutoCloseable 自动关闭,无论正常 / 异常;关闭异常附 suppressed 异常,无资源泄漏,代码简洁
  2. 手动 close:必须 finally 关闭,代码冗余;忘记关闭导致文件句柄、连接泄漏

21. Error vs Exception

维度:是否捕获、产生原因、处理策略

  1. Error:系统级致命错误 (OutOfMemory、StackOverflow),无需捕获,程序无法恢复
  2. Exception:业务异常,分运行时异常 (无需捕获)、受检异常 (编译强制捕获),可业务兜底处理

22. 受检异常 vs 运行时异常

维度:编译校验、抛出声明、适用场景

  1. 受检异常:继承 Exception 非 RuntimeException;编译强制 try-catch 或 throws;IO、文件、网络等外部不可控异常
  2. 运行时异常:RuntimeException;编译不校验;空指针、数组越界、参数错误等代码逻辑问题

23. JVM 栈 vs 堆 vs 元空间 Metaspace

维度:存储内容、生命周期、GC、内存溢出

  1. 虚拟机栈:局部变量、栈帧;方法执行完毕释放;栈深度不够 StackOverflow
  2. 堆:所有对象实例、数组;GC 回收;对象过多 OOM 堆溢出
  3. 元空间:类元信息、常量、注解;本地内存;类加载过多 Metaspace 溢出

24. 标记清除 / 复制 / 标记整理 GC 算法对比

  1. 标记清除:速度快,产生大量内存碎片;老年代 CMS 使用
  2. 复制算法:无碎片,需要预留一半内存;新生代 Minor GC
  3. 标记整理:无碎片,移动对象开销大;老年代 G1、Serial Old

25. 泛型?extends T vs ? super T

维度:读写、使用场景

  1. ? extends T:上界通配符,只能读不能写;生产者场景 (获取数据)
  2. ? super T:下界通配符,只能写不能读;消费者场景 (存入数据)
  3. PECS 原则:Producer Extends,Consumer Super

26. Iterator 迭代器 vs fori 普通循环

维度:并发修改、遍历范围、索引操作

  1. Iterator:遍历中调用迭代器 remove 安全;无下标,无法精准定位元素
  2. fori 循环:可获取下标,支持随机访问;遍历内集合 add/remove 触发并发修改异常

27. @Transactional public 方法 vs private 方法

维度:AOP 拦截、事务生效

  1. public:Spring AOP 动态代理可拦截,事务正常生效
  2. private:代理无法拦截私有方法,注解失效,无事务控制

28. new Thread () 手动创建 vs 线程池 ThreadPoolExecutor

维度:复用、开销、管控、拒绝策略

  1. new Thread:线程一次性,频繁创建销毁开销巨大;无线程管控,线程无限暴涨无限制
  2. 线程池:复用线程,控制最大并发、阻塞队列、拒绝策略;统一管控异步任务,生产环境强制使用

29. List.subList () vs 新建 ArrayList 拷贝集合

维度:数据关联、内存、修改影响

  1. subList:原集合视图,不创建新对象;修改分片 / 原集合互相影响;clear 仅清空视图不释放原数据
  2. new ArrayList<>(list):完整拷贝新集合,数据完全隔离;互不影响,占用双倍内存

30. 串行流 stream () vs 并行流 parallelStream ()

维度:线程池、顺序、IO 任务、数据量、性能

  1. 串行流:单线程执行,有序;无全局线程池抢占;适合小数据、有序业务逻辑
  2. 并行流:ForkJoin 公共池多线程;不保证遍历顺序;适合纯内存大数据计算;禁止 IO、RPC 阻塞任务,会污染全局并行任务池
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值