Java 30 组技术知识点表格对比
1. ArrayList VS LinkedList
表格
| 对比维度 | ArrayList | LinkedList |
|---|---|---|
| 底层结构 | 动态数组,连续内存 | 双向链表,离散节点 |
| 随机下标查询 | O (1),速度极快 | O (n),需要遍历节点 |
| 尾部新增元素 | 无扩容时很快,扩容需数组复制 | 仅修改指针,无数组拷贝 |
| 头部 / 中间增删 | 元素移位,性能差 | 仅修改前后指针,速度快 |
| 内存占用 | 仅存储数据,开销小 | 每个节点存 prev、next 指针,内存开销大 |
| 遍历推荐方式 | 普通 fori、foreach 均高效 | 禁止 fori 遍历,仅 foreach |
| 适用场景 | 查询多、尾部新增频繁,绝大多数业务 | 频繁头尾插入删除、用作队列 / 栈 |
2. HashMap VS ConcurrentHashMap(JDK8)
表格
| 对比维度 | HashMap | ConcurrentHashMap |
|---|---|---|
| 线程安全 | 线程不安全,并发会丢数据、死循环 | 线程安全 |
| 并发锁机制 | 无锁 | CAS + synchronized 锁住链表 / 红黑树头节点,锁粒度细 |
| null 支持 | 允许 1 个 null key,多个 null value | key、value 均不允许 null,直接 NPE |
| 并发扩容 | 并发扩容会出现链表循环死链 | 分段迁移,并发扩容安全 |
| 底层结构 | 数组 + 链表 + 红黑树 | 数组 + 链表 + 红黑树 |
| 适用场景 | 单线程场景 | 多线程并发读写缓存场景 |
3. HashMap VS LinkedHashMap VS TreeMap
表格
| 对比维度 | HashMap | LinkedHashMap | TreeMap |
|---|---|---|---|
| 有序性 | 完全无序 | 插入有序 / 访问有序 | Key 自然升序排列 |
| 底层结构 | 哈希表 | 哈希表 + 双向链表 | 红黑树 |
| 读写效率 | O (1),速度最快 | O (1),略慢于 HashMap | O (logn),速度最慢 |
| 排序规则 | 无排序 | 插入顺序 / 访问顺序 | 实现 Comparable 或自定义比较器 |
| 典型场景 | 普通键值存储 | 有序遍历、简易 LRU 缓存 | 需要按 key 排序的场景 |
4. ArrayList VS CopyOnWriteArrayList
表格
| 对比维度 | ArrayList | CopyOnWriteArrayList |
|---|---|---|
| 线程安全 | 不安全 | 线程安全 |
| 读取性能 | 单线程读取极快 | 无锁读取,多线程读性能优秀 |
| 写入性能 | 轻量,开销小 | 写入复制完整数组,开销巨大 |
| 遍历并发修改 | 遍历增删抛 ConcurrentModificationException | 迭代基于快照,无并发修改异常 |
| 适用场景 | 单线程操作集合 | 读多写少,配置缓存、白名单 |
5. synchronized VS ReentrantLock
表格
| 对比维度 | synchronized | ReentrantLock |
|---|---|---|
| 底层实现 | JVM 底层内置,自动释放 | AQS 同步队列,API 手动控制 |
| 公平锁 | 仅非公平锁 | 支持公平 / 非公平锁切换 |
| 阻塞中断 | 阻塞后不可中断 | lockInterruptibly () 支持中断等待 |
| 限时等待 | 不支持 | tryLock (时间),超时自动放弃竞争 |
| 释放规则 | 代码块执行完自动释放 | 必须在 finally 手动 unlock,否则死锁 |
| 多条件等待 | 仅 1 个 wait 等待队列 | 支持多个 Condition 条件变量 |
6. volatile VS synchronized
表格
| 对比维度 | volatile | synchronized |
|---|---|---|
| 可见性 | 保证变量可见性 | 保证可见性 |
| 原子性 | 不保证,i++ 等复合操作不安全 | 保证操作原子性 |
| 指令重排 | 禁止读写前后指令重排 | 完全禁止临界区内指令重排 |
| 锁机制 | 无锁,轻量级 | 独占互斥锁,存在线程上下文切换 |
| 适用场景 | 布尔状态标记、双重检查锁单例 | 多线程复合操作、计数、数据修改 |
7. Runnable VS Callable
表格
| 对比维度 | Runnable | Callable |
|---|---|---|
| 方法返回值 | run () 无返回值 | call () 支持泛型返回值 |
| 受检异常 | 不可抛出,只能内部捕获 | 可抛出任意受检异常 |
| 线程池返回结果 | submit 无返回对象 | submit 返回 Future,可获取执行结果 |
| 使用场景 | 无需获取任务执行结果 | 异步任务需要返回数据、捕获异常 |
8. CountDownLatch VS CyclicBarrier
表格
| 对比维度 | CountDownLatch | CyclicBarrier |
|---|---|---|
| 复用性 | 一次性,计数归零无法重置 | 可循环复用,等待完成自动重置 |
| 等待逻辑 | 一组子任务执行完,主线程等待 | 多个线程互相等待,全部到达屏障再一起执行 |
| 典型场景 | 主线程等待批量查询、多接口汇总计算 | 多线程分段计算,全部完成后合并结果 |
9. parallelStream VS CompletableFuture 自定义线程池
表格
| 对比维度 | parallelStream | CompletableFuture (自定义线程池) |
|---|---|---|
| 线程池来源 | 全局共享 ForkJoinPool | 开发者自定义隔离线程池 |
| IO 阻塞影响 | IO 阻塞任务会拖垮全局所有并行流 | 任务隔离,互不影响其他业务 |
| 线程数量控制 | 固定等于 CPU 核心数,无法自定义 | 可自由设置核心、最大线程数 |
| 适用场景 | 纯内存、无 IO 大数据计算 | RPC、数据库、文件 IO 等阻塞异步任务 |
10. Stream 中间操作 VS 终止操作
表格
| 对比维度 | 中间操作 (filter/map/sorted) | 终止操作 (collect/forEach/count) |
|---|---|---|
| 执行时机 | 惰性求值,不会立刻执行 | 立即触发整条流计算逻辑 |
| 返回值类型 | 返回全新 Stream 对象 | 无 Stream 返回,返回集合 / 数值 / Optional |
| 流消耗 | 不消耗原始流 | 一次性消费流,流直接关闭不可复用 |
| 代码生效条件 | 必须搭配终止操作才会执行 | 单独调用即可执行全部链路 |
11. map() VS flatMap()
表格
| 对比维度 | map | flatMap |
|---|---|---|
| 转换规则 | 一对一转换 T→R | T→Stream<R>,拆解嵌套集合 |
| 嵌套集合处理 | 生成 Stream<List<T>>,无法扁平化 | 拆解多层嵌套,输出单层流 |
| 典型场景 | 实体简单字段映射 | List<List>、多层集合扁平化处理 |
12. Optional.orElse() VS orElseGet()
表格
| 对比维度 | orElse(T) | orElseGet(Supplier) |
|---|---|---|
| 执行时机 | 无论 Optional 是否为空,参数一定执行 | 仅对象为空时才执行传入方法 |
| 参数类型 | 直接传入对象常量 | 无参函数,动态生成对象 |
| 性能表现 | 耗时方法会产生无效开销 | 无多余执行,性能更优 |
| 推荐场景 | 常量默认值、简单字符串 | 数据库查询、RPC 等耗时操作 |
13. Optional.of() VS Optional.ofNullable()
表格
| 对比维度 | Optional.of() | Optional.ofNullable() |
|---|---|---|
| 入参 null 处理 | 传入 null 直接抛出空指针 | 传入 null 返回 Optional.empty () |
| 使用前提 | 明确对象一定不为 null | 不确定对象是否为空,通用场景 |
14. String 拼接 + VS StringBuilder VS StringBuffer
表格
| 对比维度 | 字符串 + | StringBuilder | StringBuffer |
|---|---|---|---|
| 线程安全 | 单线程安全 | 非线程安全 | synchronized 加锁,线程安全 |
| 循环性能 | 大量循环生成大量中间字符串,性能极差 | 单线程高性能,推荐首选 | 加锁损耗,性能偏低 |
| 编译优化 | 少量拼接编译期优化为 StringBuilder | 无优化,原生高效拼接 | 无优化 |
| 适用场景 | 少量固定字符串拼接 | 单线程循环大量拼接 | 极少多线程并发拼接字符串 |
15. == VS equals()
表格
| 对比维度 | == | equals() |
|---|---|---|
| 基本类型 | 直接比较数值 | 不可使用 |
| 引用类型 | 对比内存地址是否相同 | Object 原生同 ==;String / 包装类重写对比内容 |
| 自定义实体 | 永远判断地址 | 需手动重写 equals+hashCode,实现业务字段对比 |
16. 基本数据类型 VS 包装类
表格
| 对比维度 | 基本类型 (byte/int 等) | 包装类 (Integer/Long 等) |
|---|---|---|
| 存储位置 | 虚拟机栈 | 堆内存创建对象实例 |
| 默认值 | 有固定默认值 (int=0) | 默认 null,可赋值空 |
| 空值支持 | 不能赋值 null,编译报错 | 允许 null,易触发空指针 |
| 缓存机制 | 无缓存 | -128~127 缓存池,区间外 == 判断为 false |
| 开销 | 无对象头,内存占用极小 | 存在对象头,内存开销大 |
17. final 修饰 变量 / 方法 / 类
表格
| 对比维度 | final 修饰变量 | final 修饰方法 | final 修饰类 |
|---|---|---|---|
| 修改限制 | 基本类型值不可变;引用地址不可变,内部属性可修改 | 子类无法重写该方法 | 禁止被继承,所有方法隐式 final |
| 性能优化 | 无优化 | 消除动态绑定,轻微优化 | 无动态分派,优化访问速度 |
| 代表示例 | final int MAX = 100 | 工具类内部私有方法 | String、Integer |
18. 抽象类 abstract class VS JDK8 + 接口 Interface
表格
| 对比维度 | 抽象类 | 接口 |
|---|---|---|
| 构造方法 | 拥有构造方法,供子类调用 | 无构造方法,不能实例化 |
| 成员变量 | 支持任意访问修饰符变量 | 变量默认 public static final 常量 |
| 继承实现 | 单继承,只能继承一个父类 | 多实现,可同时实现多个接口 |
| 代码块 | 支持静态代码块、实例代码块 | 仅 JDK9 支持私有方法,无实例代码块 |
| 核心定位 | 抽取子类公共状态与行为 | 定义行为契约,无业务状态 |
19. 重载 Overload VS 重写 Override
表格
| 对比维度 | 重载 Overload | 重写 Override |
|---|---|---|
| 所在类 | 同一个类中 | 父子继承类之间 |
| 方法签名 | 方法名相同,参数列表不同 | 方法名、参数、返回值完全一致 |
| 返回值 | 返回值类型无限制 | 协变返回,不能随意修改 |
| 访问权限 | 任意权限无限制 | 子类权限不能比父类更严格 |
| 受检异常 | 无限制 | 不能抛出比父类更宽泛的受检异常 |
20. try-with-resources VS 手动 close ()
表格
| 对比维度 | try-with-resources | 手动 finally close |
|---|---|---|
| 关闭时机 | 实现 AutoCloseable,自动关闭资源 | 必须手动在 finally 执行关闭 |
| 异常处理 | 关闭异常作为抑制异常保存堆栈 | 关闭异常会覆盖业务异常 |
| 代码简洁度 | 代码精简,无冗余释放逻辑 | 大量冗余 finally 模板代码 |
| 泄漏风险 | 几乎无资源泄漏风险 | 忘记 close 会造成文件句柄、连接泄漏 |
21. Error VS Exception
表格
| 对比维度 | Error | Exception |
|---|---|---|
| 异常层级 | Throwable 顶层分支 | Throwable 分支,业务异常父类 |
| 产生原因 | JVM 系统致命故障 | 代码逻辑、外部资源业务问题 |
| 处理策略 | 无需捕获,程序无法恢复 | 可捕获、自定义兜底处理 |
| 典型案例 | OOM 堆溢出、栈溢出 StackOverflow | 空指针、IO 异常、参数非法 |
22. 受检异常 VS 运行时异常
表格
| 对比维度 | 受检异常 (Exception) | 运行时异常 (RuntimeException) |
|---|---|---|
| 编译校验 | 强制 try-catch 或 throws 声明 | 编译无强制校验 |
| 触发场景 | 外部不可控资源:文件、网络、数据库 | 代码逻辑错误:空指针、数组越界、参数错误 |
| 处理思路 | 预判外部故障,提前捕获兜底 | 修复代码逻辑,提前增加参数校验 |
23. JVM 栈 VS 堆 VS 元空间 Metaspace
表格
| 对比维度 | 虚拟机栈 | 堆 | 元空间 Metaspace |
|---|---|---|---|
| 存储内容 | 局部变量、栈帧、方法调用信息 | 所有对象实例、数组 | 类元信息、常量、注解 |
| 内存来源 | JVM 虚拟机内存 | JVM 堆内存 | 操作系统本地内存 |
| GC 回收 | 方法执行完毕自动销毁,无 GC | 全程 GC 管理回收 | 类卸载才释放,极少 GC |
| 溢出异常 | StackOverflowError | OutOfMemoryError(Java heap space) | Metaspace OOM |
24. GC 算法:标记清除 / 复制 / 标记整理
表格
| 对比维度 | 标记清除 | 复制算法 | 标记整理 |
|---|---|---|---|
| 内存碎片 | 产生大量不连续内存碎片 | 无任何内存碎片 | 无内存碎片,对象规整排列 |
| 内存开销 | 仅标记清除,开销小 | 需要预留一半内存作为复制区 | 移动存活对象,开销大 |
| 适用区域 | 老年代 CMS 收集器 | 新生代 Minor GC | 老年代 Serial Old、G1 |
25. 泛型通配符?extends T VS ? super T
表格
| 对比维度 | ? extends T(上界) | ? super T(下界) |
|---|---|---|
| 读取操作 | 可以安全读取,返回 T 类型 | 读取只能返回 Object,无法强转 T |
| 写入操作 | 无法存入任意对象,编译报错 | 可以存入 T 及其子类对象 |
| 设计原则 | PECS 生产者 Producer | PECS 消费者 Consumer |
| 使用场景 | 读取数据集合 List<? extends User> | 写入数据集合 List<? super User> |
26. Iterator 迭代器 VS fori 普通循环
表格
| 对比维度 | Iterator 迭代遍历 | fori 下标循环 |
|---|---|---|
| 集合增删安全 | 迭代器 remove () 安全,无并发修改异常 | 循环内 add/remove 直接抛异常 |
| 下标获取 | 无法获取当前元素下标 | 可自由获取下标,支持随机访问 |
| 适用容器 | 所有 Collection 集合 | 仅支持实现 RandomAccess 的集合 (ArrayList) |
27. @Transactional public VS private 方法
表格
| 对比维度 | public 方法 | private 方法 |
|---|---|---|
| AOP 代理拦截 | CGLIB/JDK 动态代理可拦截 | 代理无法访问私有方法,拦截失效 |
| 事务生效情况 | 事务正常开启、提交、回滚 | 注解完全失效,无事务管理 |
| 调用限制 | 外部类可直接调用 | 仅本类内部可调用 |
28. new Thread 手动创建 VS 线程池 ThreadPoolExecutor
表格
| 对比维度 | new Thread() | ThreadPoolExecutor 线程池 |
|---|---|---|
| 线程复用 | 一次性线程,执行完销毁 | 线程复用,减少创建销毁开销 |
| 并发管控 | 无线程上限,线程无限暴涨 | 可控制核心线程、最大并发数 |
| 任务策略 | 无阻塞队列、拒绝策略 | 支持阻塞队列、4 种拒绝策略 |
| 生产规范 | 禁止线上使用 | 生产环境异步任务强制使用 |
29. List.subList () VS new ArrayList<>(list) 拷贝
表格
| 对比维度 | subList | new ArrayList<>(原集合) |
|---|---|---|
| 数据关联 | 原集合视图,不产生新数据 | 完整拷贝全新集合,数据隔离 |
| 互相影响 | 修改分片 / 原集合双向同步影响 | 两个集合完全独立,互不干扰 |
| 内存占用 | 仅创建视图对象,几乎无额外内存 | 占用双倍内存,存储两份数据 |
| clear 效果 | 仅清空分片视图,原集合数据不变 | 新集合清空不影响原始集合 |
30. stream () 串行流 VS parallelStream 并行流
表格
| 对比维度 | stream () 串行流 | parallelStream () 并行流 |
|---|---|---|
| 执行线程 | 单线程顺序执行 | 全局 ForkJoinPool 多线程并发 |
| 遍历顺序 | 严格保证集合原有顺序 | 无法保证元素处理、遍历顺序 |
| 阻塞任务 | 无全局线程池污染风险 | IO/RPC 阻塞会占用公共线程池 |
| 数据量适配 | 小数据、有序业务逻辑 | 纯内存、无 IO、超大数据批量计算 |
