常见JAVA集合面试题(自用整理,持续更新)

一、简要介绍 Java 集合框架的整体架构

        1.Java 集合框架主要分为两大接口体系:Collection 和 Map

        2.Collection 是单列集合的根接口,下面又有三个子接口,分别是 List(有序、可重复)、Set(无序、不可重复)和 Queue(队列)。

        3.Map 是双列集合的根接口,用于存储键值对。

        4.以下是java集合的基础架构图

常见JAVA集合面试题(自用整理,持续更新)_第1张图片

         5.Java 集合框架的核心继承关系图(文本描述版)

 
  
  1. ├─ Collection 接口(单列集合的根接口)

  2. │ ├─ List 接口(有序、可重复)

  3. │ │ ├─ ArrayList(动态数组实现,非线程安全)

  4. │ │ ├─ LinkedList(双向链表实现,非线程安全)

  5. │ │ └─ Vector(动态数组实现,线程安全,已过时)

  6. │ │ └─ Stack(继承自 Vector,后进先出栈结构)

  7. │ ├─ Set 接口(无序、不可重复)

  8. │ │ ├─ HashSet(基于哈希表,非线程安全)

  9. │ │ │ └─ LinkedHashSet(HashSet + 链表维护插入顺序)

  10. │ │ └─ TreeSet(基于红黑树,支持排序)

  11. │ └─ Queue 接口(队列,FIFO 原则)

  12. │ ├─ PriorityQueue(优先级队列,基于堆结构)

  13. │ └─ Deque 接口(双端队列)

  14. │ └─ LinkedList(实现 Deque)

  15. └─ Map 接口(双列集合,键值对存储)

  16. ├─ HashMap(基于哈希表,非线程安全)

  17. │ └─ LinkedHashMap(HashMap + 链表维护顺序)

  18. ├─ TreeMap(基于红黑树,支持键排序)

  19. └─ Hashtable(线程安全,已过时,不允许 null 键值)

  20. └─ Properties(继承自 Hashtable,用于配置文件)

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

需要全套面试笔记【点击此处即可】免费获取

 二、Collection 和 Collections 有什么区别?

        Collection是Java集合框架中的(顶层)接口,表示一组对象的集合。它定义了集合的基本行为,如添加、删除、遍历等操作。

        Collections是一个工具类,提供了一系列静态方法来操作各种集合对象,包括对集合排序、查找最大最小值、反转、随机化等操作。它并不是一个集合接口或类,而是一组方法的集合,用于方便对集合进行操作。

        以下是对Collection和Collections的一些代码使用介绍

 
   
  1. import java.util.ArrayList;

  2. import java.util.Collections;

  3. import java.util.Collection;

  4. public class CollectionExample {

  5. public static void main(String[] args) {

  6. // 创建一个ArrayList集合

  7. Collection list = new ArrayList<>();

  8. // 向集合中添加元素

  9. list.add("Apple");

  10. list.add("Banana");

  11. list.add("Orange");

  12. // 使用Collections工具类对集合进行操作

  13. System.out.println("原始集合:" + list);

  14. // 使用Collections工具类进行排序

  15. Collections.sort((List) list);

  16. System.out.println("排序后的集合:" + list);

  17. // 使用Collections工具类进行反转

  18. Collections.reverse((List) list);

  19. System.out.println("反转后的集合:" + list);

  20. }

  21. }

AI写代码java运行

 三、List、Set和Map之间的区别是什么?

        List是有序集合,可以包含重复元素。

        Set是无序集合,不允许重复元素。

        Map是键值对的集合,每个键唯一对应一个值,键和值都可以是任意对象。

四、List的子类有哪些?它们之间有什么区别?

  • ArrayList、LinkedList、Vector是List的子类。
  • ArrayList是基于动态数组实现的,适合随机访问和遍历。
  • LinkedList是基于链表实现的,插入和删除操作效率高。
  • Vector是线程安全的动态数组,通常不推荐使用,可以使用ArrayList代替。

五、 Set的子类有哪些?它们之间有什么区别?

  • HashSet、TreeSet、LinkedHashSet是Set的子类。
  • HashSet是基于哈希表实现的,无序且不允许重复元素。
  • TreeSet是基于红黑树实现的,元素有序且不允许重复,支持自然排序和定制排序。
  • LinkedHashSet是基于哈希表和链表实现的,具有插入顺序。

六、 Queue的常见实现类有哪些?它们之间有什么区别?

  • LinkedList、PriorityQueue是Queue的常见实现类。
  • LinkedList可以作为队列和栈来使用,实现了Queue和Deque接口。
  • PriorityQueue是优先级队列,根据元素的自然顺序或自定义比较器排序。

七、 Map的常见实现类有哪些?它们之间有什么区别?

  • HashMap、TreeMap、LinkedHashMap是Map的常见实现类。
  • HashMap基于哈希表实现,无序且允许键和值为null。
  • TreeMap基于红黑树实现,键有序且不允许键为null,支持自然排序和定制排序。
  • LinkedHashMap基于哈希表和双向链表实现,保持插入顺序或访问顺序。

八、常用集合线程安全总结表格

接口 实现类 线程安全 替代方案 特点 适用场景
List ArrayList 非线程安全 Collections.synchronizedList()
CopyOnWriteArrayList
动态数组,查询快、增删慢,允许null元素 单线程环境下的快速访问
LinkedList 非线程安全 Collections.synchronizedList()
CopyOnWriteArrayList
双向链表,增删快、查询慢,允许null元素 频繁增删的单线程场景
Vector 线程安全(过时) CopyOnWriteArrayList 动态数组,线程安全,性能低,已被Collections.synchronizedList()替代 遗留代码兼容
Stack 线程安全(过时) 使用Deque实现(如 ArrayDeque) 继承自 Vector,后进先出(LIFO)结构 栈结构需求,但推荐使用Deque
Set HashSet 非线程安全 Collections.synchronizedSet()
ConcurrentHashSet
基于哈希表,无序且不可重复,允许null元素 单线程下快速查找和去重
TreeSet 非线程安全 Collections.synchronizedSortedSet()
ConcurrentSkipListSet
基于红黑树,有序且不可重复,不允许null元素 单线程下需要排序的场景
LinkedHashSet 非线程安全 无直接替代,需手动同步 维护插入顺序,基于哈希表 + 链表 需要有序且去重的单线程场景
Map HashMap 非线程安全 Collections.synchronizedMap()
ConcurrentHashMap
基于哈希表,键唯一,允许null键值 单线程下快速键值对操作
TreeMap 非线程安全 Collections.synchronizedSortedMap()
ConcurrentSkipListMap
基于红黑树,键有序,不允许null 单线程下需要键排序的场景
Hashtable 线程安全(过时) ConcurrentHashMap 线程安全,不允许null键值,性能低,已被ConcurrentHashMap替代 遗留代码兼容
LinkedHashMap 非线程安全 无直接替代,需手动同步 维护插入顺序或访问顺序,适合缓存场景 需要有序键值对的单线程场景

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

需要全套面试笔记【点击此处即可】免费获取

 九、ArrayList 和 LinkedList 的区别?

       关键点

  • 数据结构ArrayList是动态数组,LinkedList是双向链表。
  • 增删性能LinkedList头尾操作快,ArrayList中间操作慢。
  • 查询性能ArrayList通过索引直接访问,查询快。

         扩展

        ArrayList默认容量为 10,扩容为原容量的 1.5 倍。

十、HashMap 的底层结构? 

        关键点

  • JDK 1.7:数组 + 链表。
  • JDK 1.8:数组 + 链表 + 红黑树(链表长度≥8 且容量≥64 时转换)。

        扩展 

  • 扩容触发条件:当前元素数量超过loadFactor(默认 0.75)× 容量。
  • 扩容为 2 倍,需重新计算哈希值并迁移数据。

十一、HashSet 和 TreeSet 的区别? 

        关键点

  • HashSet基于哈希表,无序;TreeSet基于红黑树,有序。
  • TreeSet不允许null元素,HashSet允许。

十二、HashMap 和 Hashtable 的区别? 

        关键点

  • Hashtable线程安全(synchronized),不允许null键值;HashMap非线程安全,允许null键值。
  • ConcurrentHashMap替代Hashtable,性能更高。

十三、ConcurrentHashMap 的实现原理? 

        关键点

  • JDK 1.7:分段锁(Segment),每个Segment独立加锁。
  • JDK 1.8:CAS+synchronized,锁粒度细化到节点。

        扩展 

ConcurrentHashMap支持高并发,吞吐量远高于Hashtable

十四、说说Vector 和 ArrayList 的区别? 

  • Vector线程安全(synchronized),扩容为原容量的 2 倍;
  • ArrayList非线程安全,扩容为 1.5 倍。

十五、说说什么是hash冲突,并说说如何解决hash冲突

         (PS:如何回答此面试题,说说鄙人之见)

        1.定义hash冲突

        哈希冲突是指不同的键经过哈希函数计算后得到相同的哈希值,导致它们被分配到哈希表的同一个桶中。

        概念很长,可能不太好理解,可以借着以下的话来辅助理解:

        哈希冲突就好比是在分配房间号的时候,不同的人由于名字相同(键经过哈希函数计算后得到相同的哈希值),导致他们被分配到了同一个房间(哈希表的同一个桶)里面。

        2. 列举解决hash冲突的方法

        常见hash冲突解决方法总结,如下表格

方法 原理 典型应用场景 优缺点
链地址法(Separate Chaining) 将同一桶中的元素用链表或红黑树存储,冲突时追加到链表尾部或树中。 Java 的HashMapHashSet(JDK 1.8 后链表长度超过 8 转为红黑树)。 优点:实现简单,冲突处理高效;
缺点:链表过长时查询性能下降。
开放定址法(Open Addressing) 冲突时在哈希表中寻找下一个可用位置(通过探测序列)。 Java 的ThreadLocal.ThreadLocalMap 优点:节省空间,无需额外存储结构;
缺点:可能导致 “二次聚集”,影响性能。
再哈希法(Rehashing) 冲突时使用不同的哈希函数重新计算哈希值,直到找到可用桶。 部分数据库索引优化场景。 优点:减少哈希冲突概率;
缺点:多次计算哈希值增加开销。
建立公共溢出区 所有冲突元素统一存储在另一个溢出区,主哈希表只存储非冲突元素。 早期哈希表实现(如 C 语言中的某些库)。 优点:结构简单;
缺点:溢出区访问效率低,维护复杂。
扩容(Resizing) 当哈希表负载因子超过阈值时,扩容哈希表并重新分配元素(即 “再哈希”)。 Java 的HashMap(默认负载因子 0.75)。 优点:降低冲突概率,提升整体性能;
缺点:扩容操作耗时,需权衡扩容阈值。

        3.结合具体场景举例

        HashSet 和 HashMap 使用链地址法存储冲突元素。当链表长度超过 8 时,会转换为红黑树以提升查询效率。此外,HashMap 的扩容机制会动态调整哈希表大小,减少冲突的发生。

         4.解决哈希冲突的核心

        选择高效的冲突处理策略和合理的哈希表参数(如负载因子),以平衡空间和时间复杂度。

你可能感兴趣的:(常见JAVA集合面试题(自用整理,持续更新))