1.2 快速复习——ArrayList 原理&面试题汇总

194 阅读3分钟

Java ArrayList 原理及面试题总结

简介

ArrayList 是 Java 集合框架中最常用的动态数组实现,提供了快速随机访问的能力。它是 List 接口的非同步实现,允许包含重复元素,并且可以包含 null 值。本文将简要介绍 ArrayList 的工作原理,并总结一些常见的面试题。

原理

ArrayList 在内部使用一个可动态扩展的数组(Object[] 类型)来存储元素。当添加元素到 ArrayList 时,如果当前数组容量不足以添加新元素,会自动进行扩容。扩容过程中,ArrayList 会创建一个新的数组,其容量为原数组容量的 1.5 倍,并复制原数组中的元素到新数组中。

扩容机制

  • ArrayList 的大小超过其容量时,需要进行扩容。
  • 默认初始容量为 10,加载因子(扩容因子)为 0.5,即当 ArrayList 的大小达到 15 时进行扩容。
  • 扩容时,创建一个新数组,其长度为原数组长度的 1.5 倍,并将原数组元素复制到新数组中。

扩容复制使用System.arraycopy方法,这是定义在 java.lang.System 类中的一个静态 native 方法,在其底层实现中,会根据传入的参数计算源数组和目标数组的内存地址,然后执行内存块的复制操作。这个操作通常是通过调用操作系统提供的内存复制函数来完成的,例如在 Linux 系统中可能会使用 memcpy 函数。

面试题总结

1. ArrayList 能否包含 null 值?

可以。ArrayList 允许存储 null 值,但只允许存储一个 null 元素。

2. ArrayListLinkedList 的区别是什么?

  • 访问性能ArrayList 提供快速的随机访问能力,而 LinkedList 在随机访问时性能较差。
  • 内存消耗ArrayList 占用的内存较少,LinkedList 需要额外存储节点引用。
  • 插入和删除ArrayList 在非尾部插入或删除元素时需要移动后续元素,而 LinkedList 可以在任意位置高效地进行插入和删除操作。

3. ArrayList 的初始容量和负载因子是什么意思?

ArrayList 有初始容量的概念,这是指创建 ArrayList 时数组的大小。但需要注意的是,ArrayList 没有负载因子的概念,这是 HashMap 的一个特性。负载因子用于决定 HashMap 的扩容时机。

4. ArrayList 的扩容机制是怎样的?

ArrayList 的元素数量超过其当前容量时,会自动扩容。扩容时,会创建一个新的数组,其长度为原数组长度的 1.5 倍,并将原数组中的元素复制到新数组中。

5. ArrayList 为什么不是线程安全的?

ArrayList 并不是为线程安全设计的。它的所有操作都不是同步的,这意味着在多线程环境下,如果多个线程同时修改 ArrayList,可能会导致不可预测的结果。

6. 如何实现一个不可修改的 ArrayList

可以使用 Collections.unmodifiableList 方法来创建一个不可修改的 ArrayList。任何试图修改这个 ArrayList 的操作都会抛出 UnsupportedOperationException 异常。

7. ArrayListget(int index) 方法时间复杂度是多少?

ArrayListget(int index) 方法时间复杂度为 O(1),因为它直接通过索引访问数组元素。

8. ArrayListadd(E e) 方法在什么情况下会抛出异常?

ArrayListadd(E e) 方法通常不会抛出异常,除非 enull 并且 ArrayList 禁止存储 null 值,或者 e 的类型与 ArrayList 存储的元素类型不兼容。

参考链接

ArrayList 原理&面试题汇总