Java集合最全面试题(25秋招走起)

List 接口

1.List、Set、Map 之间的区别

  1. List(列表)
    • 有序性:List 是有序集合,元素的顺序是按照它们被添加的顺序来存储和访问的。你可以通过索引来访问列表中的元素。
    • 元素重复性:List 允许存储重复的元素,同一个元素可以出现多次。
  1. Set(集合)
    • 无序性:Set 是无序集合,元素之间没有明确的顺序。你不能通过索引来访问集合中的元素。
    • 元素唯一性:Set 中不允许存储重复的元素,每个元素在集合中只能出现一次。
  1. Map
    • 存储键值对:Map 存储键值对,每个键关联一个唯一的值。这使得你可以通过键来查找和访问与之相关联的值。
    • 键的唯一性:在一个 Map 中,每个键只能出现一次,但不同的键可以关联不同的值。

2.Arraylist 与 LinkedList 的区别

  1. 内部实现
    • ArrayList 使用一个动态数组来存储元素。当元素数量增加时,ArrayList 会自动增加其底层数组的大小以容纳更多元素。
    • LinkedList 使用一个双向链表来存储元素。每个元素都包含对前一个元素和后一个元素的引用。
  1. 插入和删除操作
    • 在 ArrayList 中,插入和删除元素通常比较慢,特别是在列表的中间位置,因为需要移动元素来保持顺序。在列表末尾添加元素的操作相对较快。
    • 在 LinkedList 中,插入和删除元素通常比较快,尤其是在列表的中间位置,因为只需要更新节点的引用。但在列表末尾添加元素的操作可能比 ArrayList 慢一些,因为需要遍历链表找到末尾节点。
  1. 访问元素
    • 通过索引访问元素的操作非常快速,因为可以直接在数组中找到元素。
    • 在 LinkedList 中,通过索引访问元素需要从头节点或尾节点开始遍历链表,因此访问速度相对较慢。
  1. 内存占用
    • 由于需要预分配一定大小的数组,ArrayList 可能会浪费一些内存空间。如果数组大小超过了实际元素数量,会导致内存浪费。
    • LinkedList 比较节省内存,因为它只存储实际的元素以及每个元素的前后节点引用。
  1. 适用场景
    • ArrayList 适用于需要快速访问元素、不需要频繁插入和删除操作的情况。
    • LinkedList 适用于需要频繁插入和删除操作、不需要快速访问元素的情况。

3.ArrayList 和 Vector 的区别

ArrayList 和 Vector 都是 Java 中用于存储和操作动态数组(可变长度数组)的集合类,但他们之间还是有一些差异的:

  1. 线程安全性
    • ArrayList 是非线程安全的,这意味着在多线程环境下,如果不采取额外的同步措施,多个线程同时访问和修改 ArrayList 可能会导致数据不一致或抛出异常。
    • Vector 是线程安全的,它的方法都是同步的,这意味着在多线程环境下,多个线程可以安全地访问和修改 Vector,但这也会导致性能开销,因为每个方法都要获得锁。
  1. 性能
    • 由于不需要进行同步,ArrayList 在单线程环境下通常比 Vector 性能更好,因为它没有额外的同步开销。
    • 由于需要同步,Vector 在多线程环境下可能会有较高的性能开销,因此在单线程环境中可能不如 ArrayList 快。
  1. 增长策略
    • ArrayList 的增长策略是在当前容量不足时,将容量扩大一半。
    • Vector 的增长策略是在当前容量不足时,将容量翻倍。

综上所述,如果你在单线程环境下工作,并且不需要线程安全性,建议使用 ArrayList,因为它在性能上通常更优。如果你需要线程安全性,可以使用 Vector,但需要注意性能开销。

4.ArrayList 的扩容机制?

ArrayList 的扩容机制是在当前容量不足时自动增加其内部数组的大小,以容纳更多元素。机制如下:

  1. 初始容量: 当你创建一个 ArrayList 时,它会分配一个初始容量。默认情况下,初始容量为 10,但你可以在创建 ArrayList 时指定不同的初始容量。
  2. 添加元素: 当你向 ArrayList 添加元素时,它会检查当前元素数量是否已经达到了容量上限。如果元素数量等于或超过容量上限,就会触发扩容操作。
  3. 扩容操作: 扩容操作会创建一个新的更大的数组(通常是原来容量的 1.5 倍或 2 倍,具体取决于具体的实现),然后将所有元素从旧数组复制到新数组中。这个过程涉及数组的拷贝操作,因此具有一定的时间开销。
  4. 更新引用: 一旦新数组创建并所有元素都复制到新数组中,ArrayList 会更新内部引用,使其指向新数组。

ArrayList 采用这种扩容策略是为了平衡空间的利用和时间开销。如果每次添加元素都触发扩容,会导致性能下降,因为需要频繁地进行数组复制操作。因此,通过一次性扩容一定的大小,可以减少扩容的频率,提高整体性能。

需要注意的是,虽然扩容操作是 ArrayList 内部自动处理的,但在某些情况下,如果你知道 ArrayList 预计会存储大量元素,你可以在创建 ArrayList 时指定一个较大的初始容量,以减少扩容次数,从而提高性能。

5.Queue 与 Deque 的区别

Queue(队列)

  • Queue 是一种线性数据结构,它遵循先进先出(FIFO)的原则,即最早添加的元素最早被移除。
  • Queue 接口继承自 Collection 接口,它定义了一组用于添加、删除和检查元素的方法,如 add、offer、remove、poll、element 和 peek 等。
  • Queue 不支持在中间插入或删除元素,只能在队列的头部添加和尾部移除元素。

Deque(双端队列)

  • Deque 也是一种线性数据结构,它允许在队列的两端进行插入和删除操作,因此可以用作队列和栈的结合体。
  • Deque 接口继承自 Queue 接口,因此包含了 Queue 的所有方法,同时还定义了一组用于在两端添加和删除元素的方法,如 addFirst、addLast、removeFirst、removeLast、getFirst 和 getLast 等。
  • Deque 允许在队列的头部和尾部插入和删除元素,因此具有更灵活的使用方式。

总结一下,主要区别在于以下两点:

  • Queue 是一种遵循先进先出(FIFO)原则的线性数据结构,只支持在队列的头部添加和尾部移除元素。
  • Deque 是一种允许在队列的两端进行插入和删除操作的线性数据结构,可以用作队列和栈的结合体,具有更灵活的使用方式。

6.说一说PriorityQueue

PriorityQueue(优先队列)是一个基于优先级堆(Priority Heap)实现的队列。与普通队列不同,PriorityQueue 中的元素并不是按照它们的插入顺序进行处理,而是按照它们的优先级顺序进行处理。在 PriorityQueue 中,具有最高优先级的元素将首先被处理。

以下是关于 PriorityQueue 的一些重要特点和使用方式:

  1. 优先级顺序:PriorityQueue 中的元素按照它们的自然顺序或者根据指定的比较器(Comparator)来确定优先级。具有最高优先级的元素将位于队列的头部。
  2. 插入和删除操作:PriorityQueue 提供了插入(offer 或 add)和删除(poll 或 remove)元素的操作。插入操作会根据元素的优先级将元素放入合适的位置,删除操作会移除并返回队列中具有最高优先级的元素。
  3. 不允许 null 元素:PriorityQueue 不允许存储 null 元素,因为 null 无法用于确定元素的优先级。
  4. 底层数据结构:PriorityQueue 通常使用二叉堆(binary heap)或斐波那契堆(Fibonacci heap)等数据结构来实现。这些数据结构保证了插入和删除操作的高效性,插入和删除的时间复杂度通常为 O(log n)。
  5. 用途:PriorityQueue 在很多场景下都非常有用,例如实现优先级调度算法、Dijkstra 算法(用于求解最短路径问题)、Prim 算法(用于生成最小生成树)等。它也常用于任务调度、事件驱动编程等领域。

7.有数组了为什么还要搞个 ArrayList 呢?

通常我们在使用的时候,如果在不明确要插入多少数据的情况下,普通数组就很尴尬了,因为你不知道需要初始化数组大小为多少,而 ArrayList 可以使用默认的大小,当元素个数到达一定程度后,会自动扩容。 可以这么来理解:我们常说的数组是定死的数组,ArrayList 却是动态数组。

8.如何实现数组和 List 之间的转换?

  • List转换成为数组:调用ArrayList的toArray方法。
  • 数组转换成为List:调用Arrays的asList方法。

9.什么是 fail-fast 机制?

fail-fast 机制是 Java 集合(Collecti

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值