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;elsel.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<>(); // 选择ArrayListfor (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使用中的陷阱
- 理解内存管理和性能优化
- 掌握并发访问的处理方式