1.数组与集合区别,用过哪些?
1.
-
长度可变性: 数组是定长的,一旦创建无法扩容;集合(如
ArrayList)支持动态扩容,能自动适应数据增长。 -
存储类型: 数组既可以存储基本数据类型(int, char),也可以存储引用对象;集合只能存储引用对象(基本类型会通过自动装箱处理)。
-
功能丰富度: 数组功能单一,仅能通过索引访问;集合框架(JCF)提供了丰富的 API(如排序、搜索、去重、线程安全方案等),开发效率更高。
2.
我会按照 List、Set、Map 三大体系进行分类说明,这体现了你对体系结构的清晰认知:

-
List(有序、可重复):
-
ArrayList: 基于动态数组,随机访问快,是我在查询密集型场景的首选。
-
LinkedList: 基于双向链表,虽然随机访问慢,但在频繁头尾增删的场景下表现更好。
-
-
Set(无序、唯一):
-
HashSet: 基于
HashMap实现,用于数据去重。 -
TreeSet: 基于红黑树,适用于需要对元素进行自然排序或自定义排序的场景。
-
-
Map(键值对存储):
-
HashMap: 性能最高,最常用的键值对存储容器。
-
ConcurrentHashMap: 线程安全且高效,在高并发场景下代替
Hashtable。 -
LinkedHashMap: 维护了插入顺序,常用于实现 LRU 缓存。
-
3.Java中的线程安全的集合是什么?
| 集合分类 | 代表容器 | 实现机制 (核心原理) | 锁粒度 | 适用场景 |
|---|---|---|---|---|
| 早期遗留 | Vector / Hashtable | 方法上直接加 synchronized | 全表锁 (锁整个对象) | 基本已被淘汰,不建议使用 |
| 工具包装 | Collections.synchronizedX | 内部维护 mutex 互斥对象 | 全表锁 (对象级锁) | 并发量极小、对性能无要求的简单场景 |
| 现代并发 (Map) | ConcurrentHashMap | CAS + synchronized (Node 头节点) | 行级锁 (分段/桶锁) | 高并发 键值对读写存储 (推荐首选) |
| 现代并发 (List) | CopyOnWriteArrayList | 写时复制 (Copy-on-write) | 仅写操作加锁 (ReentrantLock) | 读多写少 (如白名单、配置缓存) |
| 阻塞队列 | ArrayBlockingQueue | ReentrantLock + Condition | 队列对象锁 | 生产者-消费者模型、线程池任务调度 |
4.Collections和Collection的区别
| 特性 | Collection (接口) | Collections (工具类) |
|---|---|---|
| 本质 | 集合层次结构的根接口 | 操作集合的静态工具类 |
| 包位置 | java.util.Collection | java.util.Collections |
| 主要用途 | 定义了所有单列集合(List, Set)的核心标准方法(如 add, remove, size)。 | 提供静态方法对集合进行搜索、排序、转换、线程安全化处理等。 |
| 继承关系 | 被 List、Set、Queue 继承。 | 继承自 Object,不能被实例化(构造方法是私有的)。 |
| 你必须记住的 Collections 常用方法(面试常问): |
-
排序:
Collections.sort(list) -
翻转:
Collections.reverse(list) -
查找:
Collections.binarySearch(list, key) -
线程安全包装:
Collections.synchronizedList(list) -
不可变集合:
Collections.unmodifiableList(list)
5.集合遍历的方法有哪些?
以下是针对 Collection(List/Set)和 Map 两个体系的分类总结:
1. Collection 体系(List、Set)的遍历
-
普通 for 循环:
-
特点:基于索引(index)访问。
-
适用场景:仅适用于实现了
RandomAccess接口的集合(如ArrayList)。如果是LinkedList,性能会极差($O(n^2)$)。
-
-
增强 for 循环 (for-each):
-
本质:Java 的语法糖,底层依赖
Iterator。 -
优点:代码简洁,可读性好。
-
缺点:在遍历过程中不能直接修改集合结构(如
remove),否则会抛出ConcurrentModificationException(fail-fast 机制)。
-
-
Iterator(迭代器):

-
特点:最标准的遍历方式。
-
核心优势:唯一可以在遍历时安全删除元素的方法(需调用
iterator.remove())。 -
forEach + Lambda (Java 8+):
-
特点:函数式编程风格,极其简洁。
-
适用场景:仅需对每个元素执行简单操作时使用。
-
2. Map 体系的遍历(面试官最看重性能)
-
EntrySet 遍历(最推荐):
for (Map.Entry<K, V> entry : map.entrySet()) { ... }- 性能最高:一次性取出 Key 和 Value。
-
KeySet 遍历:
for (K key : map.keySet()) { V value = map.get(key); }- 性能较低:如果需要 Value,每次循环还要多走一次哈希查找(
get(key))。仅当只需要 Key 时使用。
- 性能较低:如果需要 Value,每次循环还要多走一次哈希查找(
-
Map.forEach (Java 8+):
map.forEach((k, v) -> { ... });- 评价:语法最优雅,底层基于
entrySet遍历,兼顾了性能与美观。
- 评价:语法最优雅,底层基于