Java List实现类面试题
ArrayList
Q1: ArrayList的实现原理是什么?
ArrayList是基于数组实现的List,支持动态扩容。
java">public class ArrayListPrincipleExample {
// 模拟ArrayList的基本实现
public class SimpleArrayList<E> {
private static final int DEFAULT_CAPACITY = 10;
private Object[] elementData;
private int size;
public SimpleArrayList() {
elementData = new Object[DEFAULT_CAPACITY];
}
public boolean add(E e) {
ensureCapacity(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacity(int minCapacity) {
if (minCapacity > elementData.length) {
int newCapacity = Math.max(elementData.length * 3/2, minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
}
}
Q2: ArrayList的扩容机制是怎样的?
java">public class ArrayListGrowthExample {
public void demonstrateGrowth() {
// 1. 默认构造函数
ArrayList<String> list1 = new ArrayList<>(); // 初始容量为0
// 2. 指定初始容量
ArrayList<String> list2 = new ArrayList<>(20);
// 3. 扩容过程
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 11; i++) {
list.add("item" + i);
System.out.println("Size: " + list.size() +
", Capacity: " + getCapacity(list));
}
}
// 通过反射获取实际容量
private static int getCapacity(ArrayList<?> list) {
try {
Field field = ArrayList.class.getDeclaredField("elementData");
field.setAccessible(true);
return ((Object[]) field.get(list)).length;
} catch (Exception e) {
return -1;
}
}
}
LinkedList
Q3: LinkedList的实现原理是什么?
LinkedList是基于双向链表实现的List。
java">public class LinkedListPrincipleExample {
// 模拟LinkedList的基本实现
public class SimpleLinkedList<E> {
private static class Node<E> {
E item;
Node<E> prev;
Node<E> next;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.prev = prev;
this.next = next;
}
}
private Node<E> first;
private Node<E> last;
private int size;
public boolean add(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
return true;
}
}
}
Q4: ArrayList和LinkedList的性能对比?
java">public class ListPerformanceComparison {
public void comparePerformance() {
ArrayList<Integer> arrayList = new ArrayList<>();
LinkedList<Integer> linkedList = new LinkedList<>();
int n = 100000;
// 1. 添加性能对比
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
arrayList.add(i);
}
System.out.println("ArrayList添加耗时:" + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
linkedList.add(i);
}
System.out.println("LinkedList添加耗时:" + (System.currentTimeMillis() - start));
// 2. 随机访问性能对比
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
arrayList.get(i);
}
System.out.println("ArrayList随机访问耗时:" + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
linkedList.get(i);
}
System.out.println("LinkedList随机访问耗时:" + (System.currentTimeMillis() - start));
// 3. 插入性能对比
start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
arrayList.add(0, i);
}
System.out.println("ArrayList头部插入耗时:" + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
linkedList.addFirst(i);
}
System.out.println("LinkedList头部插入耗时:" + (System.currentTimeMillis() - start));
}
}
实践应用
Q5: 如何选择ArrayList和LinkedList?
java">public class ListSelectionExample {
// 1. 随机访问场景
public void randomAccess() {
List<Integer> list = new ArrayList<>(); // 选择ArrayList
for (int i = 0; i < 100000; i++) {
list.add(i);
}
// 随机访问元素
Random random = new Random();
for (int i = 0; i < 1000; i++) {
list.get(random.nextInt(list.size()));
}
}
// 2. 频繁插入删除场景
public void frequentModification() {
List<Integer> list = new LinkedList<>(); // 选择LinkedList
// 频繁在头部插入
for (int i = 0; i < 10000; i++) {
list.add(0, i);
}
// 频繁在中间删除
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
if (iterator.next() % 2 == 0) {
iterator.remove();
}
}
}
}
Q6: List的常见陷阱有哪些?
java">public class ListPitfallsExample {
// 1. 类型转换问题
public void typeCastPitfall() {
List<Integer> list = new ArrayList<>();
list.add(1);
// Integer number = list.get(0); // 自动拆箱
Integer number = (Integer) list.get(0); // 显式转换
}
// 2. 并发修改问题
public void concurrentModificationPitfall() {
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
// 错误方式
try {
for (String item : list) {
if ("1".equals(item)) {
list.remove(item);
}
}
} catch (ConcurrentModificationException e) {
System.out.println("并发修改异常");
}
// 正确方式
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("1".equals(item)) {
iterator.remove();
}
}
}
// 3. 内存泄漏问题
public void memoryLeakPitfall() {
List<Object> list = new ArrayList<>();
Object obj = new Object();
list.add(obj);
// 可能导致内存泄漏
obj = null; // 原对象仍然被list引用
// 正确方式
list.remove(0); // 先从list中移除
obj = null; // 再置空引用
}
}
面试关键点
- 理解ArrayList和LinkedList的实现原理
- 掌握ArrayList的扩容机制
- 了解LinkedList的节点结构
- 熟悉两种List的性能特点
- 掌握List的选择原则
- 注意List使用中的陷阱
- 理解内存管理和性能优化
- 掌握并发访问的处理方式