Java List实现类面试题

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

Java List实现类面试题

ArrayList

Q1: ArrayList的实现原理是什么?

ArrayList是基于数组实现的List,支持动态扩容。

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的扩容机制是怎样的?

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。

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的性能对比?

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?

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的常见陷阱有哪些?

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;      // 再置空引用
    }
}

面试关键点

  1. 理解ArrayList和LinkedList的实现原理
  2. 掌握ArrayList的扩容机制
  3. 了解LinkedList的节点结构
  4. 熟悉两种List的性能特点
  5. 掌握List的选择原则
  6. 注意List使用中的陷阱
  7. 理解内存管理和性能优化
  8. 掌握并发访问的处理方式

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值