Java 面试:集合类有哪些?List、Set、Map 怎么答才不乱?

32 阅读8分钟

摘要

Java 集合是面试里非常高频的基础题。这个问题看起来简单,但很多人一答就容易把 CollectionCollectionsListSetMapIterator 混在一起。本文用面试视角,快速梳理 Java 集合体系、常见分类、核心区别和高频追问,适合面试前快速复习。


前言

最近这段时间工作比较忙,一直没怎么更新文章。

但我发现一个问题:越忙的时候,越容易把一些基础知识忘得差不多。尤其是 Java 面试八股,平时写业务代码的时候感觉都懂,但真到面试被问起来,如果没有提前梳理,很容易答得又散又乱。

所以我准备开一个偏“速记型”的 Java 面试系列。

不追求写得特别长,也不搞太多废话,主要就是:

面试常问什么,应该怎么答,哪些点容易混,最后怎么用一段话说清楚。

第一篇就从 Java 集合开始。

Java 集合是面试里非常高频的基础题,尤其是 ListSetMapCollectionCollectionsIterator 这些概念,经常会被放在一起问。


一、面试官一般会怎么问?

集合类这个知识点,面试官通常会这么问:

  • Java 中常见的集合类有哪些?
  • ListSetMap 有什么区别?
  • CollectionCollections 有什么区别?
  • ArrayListLinkedList 有什么区别?
  • HashMapHashtable 有什么区别?
  • IteratorIterable 有什么关系?
  • 为什么集合可以用 foreach 遍历?

这篇先不展开所有集合底层原理,先把集合体系和分类讲清楚。


二、先给结论:Java 集合主要分两套体系

Java 集合大体可以分成两套体系:

  • Collection
  • Map

其中:

Collection 用来存放单个元素。

它下面常见的子接口有:

  • List
  • Set
  • Queue

Map 用来存放 key-value 键值对。

它不属于 Collection 体系。

可以简单理解成:

Java 集合体系
├── Collection
│   ├── List
│   ├── Set
│   └── Queue
└── Map

面试时不要把 Map 说成 Collection 的子接口,这个是基础但容易嘴瓢的点。


三、Collection 体系有哪些?

Collection 是 Java 集合框架中的一个顶层接口,它表示一组对象。

常见子接口主要有三个。

1. List

List 的特点是:

  • 有序
  • 可重复
  • 可以通过下标访问

常见实现类:

  • ArrayList
  • LinkedList
  • Vector

简单理解:

List 更像一个列表,元素可以重复,并且有插入顺序。

示例:

List<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("Java");

System.out.println(list);

输出:

[Java, Spring, Java]

可以看到,List 允许重复元素。


2. Set

Set 的特点是:

  • 不允许重复
  • 通常无序
  • 不能通过下标访问

常见实现类:

  • HashSet
  • LinkedHashSet
  • TreeSet

简单理解:

Set 更像一个去重集合,主要用来保证元素不重复。

示例:

Set<String> set = new HashSet<>();

set.add("Java");
set.add("Spring");
set.add("Java");

System.out.println(set);

输出结果中只会保留一个 Java

需要注意的是:

HashSet 的底层其实是基于 HashMap 实现的。

这一点后面讲 HashMap 的时候可以展开。


3. Queue

Queue 表示队列结构。

它的特点是:

  • 通常用于先进先出
  • 也可以支持优先级队列
  • 常用于任务排队、消息处理等场景

常见实现类:

  • LinkedList
  • PriorityQueue
  • ArrayDeque

简单理解:

Queue 更适合表达排队处理的场景。

示例:

Queue<String> queue = new LinkedList<>();

queue.offer("task1");
queue.offer("task2");

System.out.println(queue.poll());
System.out.println(queue.poll());

输出:

task1
task2

四、Map 体系有哪些?

MapCollection 不一样。

Map 存的是 key-value 键值对。

常见实现类:

  • HashMap
  • LinkedHashMap
  • TreeMap
  • Hashtable
  • ConcurrentHashMap

简单理解:

Map 适合根据 key 快速查找 value。

示例:

Map<String, Integer> map = new HashMap<>();

map.put("Java", 1);
map.put("Spring", 2);

System.out.println(map.get("Java"));

输出:

1

Map 最常见的使用场景就是:

  • 根据用户 ID 查用户信息
  • 根据编码查名称
  • 根据 key 缓存某个对象
  • 根据业务标识做映射

五、List、Set、Queue、Map 有什么区别?

这个问题很常见,面试时可以用表格记。

| 类型 | 是否有序 | 是否允许重复 | 典型特点 | 常见实现 | | --- | --- | --- | --- | --- | | List | 有序 | 允许重复 | 有下标,适合按顺序存储 | ArrayList、LinkedList | | Set | 不保证有序 | 不允许重复 | 适合去重 | HashSet、TreeSet | | Queue | 通常有序 | 允许重复 | 队列结构,适合排队处理 | LinkedList、PriorityQueue | | Map | key 不允许重复 | value 可重复 | key-value 键值对 | HashMap、TreeMap、ConcurrentHashMap |

面试时可以这样回答:

List 主要特点是有序、可重复,可以通过下标访问;
Set 主要特点是不允许重复,常用于去重;
Queue 偏队列结构,适合先进先出或优先级队列场景;
Map 存储的是 key-value 键值对,适合根据 key 快速查询 value。

六、Collection 和 Collections 有什么区别?

这个是经典基础题。

一句话:

Collection 是集合接口,Collections 是集合工具类。

1. Collection

Collection 是 Java 集合框架中的接口。

ListSetQueue 都是它的子接口。

2. Collections

Collections 是工具类。

它里面提供了很多操作集合的静态方法,比如:

  • 排序
  • 反转
  • 打乱
  • 查找最大值
  • 查找最小值
  • 创建线程安全集合

示例:

List<Integer> list = new ArrayList<>();

list.add(3);
list.add(1);
list.add(2);

Collections.sort(list);

System.out.println(list);

输出:

[1, 2, 3]

面试回答:

Collection 是集合体系中的顶层接口之一,List、Set、Queue 都属于它的子体系。
Collections 是一个工具类,里面提供了很多操作集合的静态方法,比如排序、反转、查找、同步包装等。
简单记就是:Collection 是接口,Collections 是工具类。

七、Iterable 和 Iterator 有什么区别?

这个也经常被问。

一句话:

Iterable 表示这个对象可以被遍历,Iterator 是真正执行遍历的迭代器。

1. Iterable

Iterable 是可迭代接口。

只要一个类实现了 Iterable,就可以使用 foreach 遍历。

比如:

List<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");

for (String item : list) {
    System.out.println(item);
}

之所以 List 能用 foreach,是因为它属于 Collection 体系,而 Collection 继承了 Iterable


2. Iterator

Iterator 是迭代器接口。

它主要有几个常见方法:

  • hasNext()
  • next()
  • remove()

示例:

List<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

面试回答:

Iterable 表示一个对象具备被遍历的能力,实现了 Iterable 的类可以使用 foreach。
Iterator 是真正执行遍历过程的迭代器,常见方法有 hasNext()、next()、remove()。
简单理解就是:Iterable 说明能遍历,Iterator 负责怎么遍历。

八、为什么 Collection 要继承 Iterable?

因为集合本质上就是一组元素。

既然是元素集合,就应该具备统一的遍历能力。

所以 Collection 继承了 Iterable,这样它下面的 ListSetQueue 都可以通过统一方式遍历。

面试时可以这样说:

Collection 继承 Iterable,是为了让集合体系具备统一的遍历能力。
这样 List、Set、Queue 等集合都可以通过 Iterator 或 foreach 的方式遍历,使用方式更加统一。

九、foreach 的底层和 Iterator 有什么关系?

foreach 本质上是一种语法糖。

对于实现了 Iterable 的集合,foreach 底层还是通过 Iterator 来完成遍历。

比如我们写:

for (String item : list) {
    System.out.println(item);
}

大致可以理解成:

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

所以面试时如果被问:

为什么集合可以用 foreach?

可以回答:

因为 Collection 继承了 Iterable,而 Iterable 提供了 iterator() 方法。
foreach 遍历集合时,底层会通过 Iterator 来完成遍历。

十、面试回答模板

如果面试官问:

Java 中的集合类有哪些?怎么分类?

可以这样答:

Java 集合大体可以分为 Collection 和 Map 两套体系。

Collection 用来存储单个元素,常见子接口有 List、Set、Queue。
List 的特点是有序、可重复,比如 ArrayList、LinkedList;
Set 的特点是不允许重复,比如 HashSet、TreeSet;
Queue 偏队列结构,比如 LinkedList、PriorityQueue。

Map 存储的是 key-value 键值对,不属于 Collection 体系。
常见实现有 HashMap、LinkedHashMap、TreeMap、ConcurrentHashMap。

另外需要注意 Collection 和 Collections 的区别:
Collection 是集合接口,Collections 是集合工具类。

这段回答不算特别深,但足够清楚。

如果面试官继续追问,再展开具体实现类的区别,比如:

  • ArrayListLinkedList
  • HashMapHashtable
  • HashMapConcurrentHashMap
  • HashSet 为什么能去重

十一、常见追问整理

1. ArrayList 和 LinkedList 有什么区别?

简单说:

  • ArrayList 底层是数组
  • LinkedList 底层是链表

区别:

  • ArrayList 查询快,增删可能慢
  • LinkedList 插入删除相对方便,但查询需要遍历

一句话:

ArrayList 适合查询多的场景,LinkedList 适合插入删除多的场景。
但实际开发中,ArrayList 用得更多。

2. HashSet 为什么能去重?

因为 HashSet 底层基于 HashMap 实现。

添加元素时,元素会作为 HashMap 的 key 存进去。

HashMap 的 key 不能重复,所以 HashSet 能去重。

一句话:

HashSet 去重依赖 HashMap 的 key 不重复,本质上还和 hashCode()、equals() 有关。

3. HashMap 是不是线程安全的?

不是。

HashMap 不是线程安全的。

多线程场景下,如果多个线程同时修改 HashMap,可能出现数据覆盖、数据不一致等问题。

多线程场景一般考虑:

  • ConcurrentHashMap
  • 或者额外加锁

一句话:

HashMap 适合单线程或局部变量场景,多线程共享修改时应该使用 ConcurrentHashMap。

4. Vector 为什么现在用得少?

Vector 是早期的线程安全 List 实现。

它的方法很多都加了 synchronized,所以线程安全,但性能相对较差。

现在实际开发中更常用:

  • ArrayList
  • CopyOnWriteArrayList
  • 或者自己控制并发场景

一句话:

Vector 比较老,虽然线程安全,但并发性能和使用灵活性都不如现在常用的并发集合。

十二、一句话总结

Java 集合大体分为 CollectionMap 两套体系。

Collection 存单个元素,常见的有 ListSetQueue
Map 存 key-value 键值对,不属于 Collection 体系。

面试时先把分类讲清楚,再展开具体实现类的特点和区别。

这类题不难,但一定要答得有层次。

别一上来就把 ArrayListHashMapHashSet 全混在一起说。

大家加油:)