Java集合框架(Collections Framework)是Java编程中最重要的特性之一,它提供了一套设计良好的接口和类来存储和操作对象集合。本章将详细介绍各种集合类型及其使用方法。

7.1 集合框架概述

7.1.1 集合框架结构

import java.util.*;

/**
 * 集合框架概述演示
 */
public class CollectionsOverview {
    public static void main(String[] args) {
        System.out.println("=== Java集合框架概述 ===");
        
        demonstrateCollectionHierarchy();
        demonstrateBasicOperations();
    }
    
    public static void demonstrateCollectionHierarchy() {
        System.out.println("\n=== 集合框架层次结构 ===");
        
        System.out.println("");
        System.out.println("Collection接口层次结构:");
        System.out.println("Collection (接口)");
        System.out.println("├── List (接口) - 有序、可重复");
        System.out.println("│   ├── ArrayList - 动态数组实现");
        System.out.println("│   ├── LinkedList - 双向链表实现");
        System.out.println("│   └── Vector - 同步的动态数组");
        System.out.println("├── Set (接口) - 无序、不可重复");
        System.out.println("│   ├── HashSet - 哈希表实现");
        System.out.println("│   ├── LinkedHashSet - 保持插入顺序的HashSet");
        System.out.println("│   └── TreeSet - 红黑树实现,自动排序");
        System.out.println("└── Queue (接口) - 队列");
        System.out.println("    ├── PriorityQueue - 优先队列");
        System.out.println("    └── Deque (接口) - 双端队列");
        System.out.println("        └── ArrayDeque - 数组实现的双端队列");
        System.out.println("");
        System.out.println("Map接口层次结构:");
        System.out.println("Map (接口) - 键值对映射");
        System.out.println("├── HashMap - 哈希表实现");
        System.out.println("├── LinkedHashMap - 保持插入顺序的HashMap");
        System.out.println("├── TreeMap - 红黑树实现,按键排序");
        System.out.println("└── Hashtable - 同步的哈希表");
    }
    
    public static void demonstrateBasicOperations() {
        System.out.println("\n=== 集合基本操作演示 ===");
        
        // Collection接口的基本方法
        Collection<String> collection = new ArrayList<>();
        
        System.out.println("\n1. 添加元素:");
        collection.add("Apple");
        collection.add("Banana");
        collection.add("Cherry");
        System.out.println("集合内容: " + collection);
        System.out.println("集合大小: " + collection.size());
        
        System.out.println("\n2. 查询操作:");
        System.out.println("是否包含Apple: " + collection.contains("Apple"));
        System.out.println("是否包含Orange: " + collection.contains("Orange"));
        System.out.println("集合是否为空: " + collection.isEmpty());
        
        System.out.println("\n3. 删除操作:");
        collection.remove("Banana");
        System.out.println("删除Banana后: " + collection);
        
        System.out.println("\n4. 批量操作:");
        Collection<String> otherCollection = Arrays.asList("Date", "Elderberry");
        collection.addAll(otherCollection);
        System.out.println("添加其他集合后: " + collection);
        
        System.out.println("\n5. 遍历操作:");
        System.out.print("使用增强for循环: ");
        for (String item : collection) {
            System.out.print(item + " ");
        }
        System.out.println();
        
        System.out.print("使用Iterator: ");
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
        
        System.out.print("使用Stream API: ");
        collection.stream().forEach(item -> System.out.print(item + " "));
        System.out.println();
        
        System.out.println("\n6. 转换为数组:");
        String[] array = collection.toArray(new String[0]);
        System.out.println("转换为数组: " + Arrays.toString(array));
        
        System.out.println("\n7. 清空集合:");
        collection.clear();
        System.out.println("清空后集合大小: " + collection.size());
    }
}

7.1.2 泛型在集合中的应用

import java.util.*;

/**
 * 泛型在集合中的应用演示
 */
public class GenericsInCollections {
    public static void main(String[] args) {
        System.out.println("=== 泛型在集合中的应用 ===");
        
        demonstrateBasicGenerics();
        demonstrateWildcards();
        demonstrateBoundedGenerics();
    }
    
    public static void demonstrateBasicGenerics() {
        System.out.println("\n--- 基本泛型使用 ---");
        
        // ❌ 不使用泛型(不推荐)
        List rawList = new ArrayList();
        rawList.add("String");
        rawList.add(123);
        rawList.add(new Date());
        
        // 需要强制类型转换,容易出错
        for (Object obj : rawList) {
            System.out.println("原始类型: " + obj + " (" + obj.getClass().getSimpleName() + ")");
        }
        
        // ✅ 使用泛型(推荐)
        List<String> stringList = new ArrayList<>();
        stringList.add("Apple");
        stringList.add("Banana");
        // stringList.add(123); // 编译错误,类型安全
        
        // 不需要类型转换
        for (String str : stringList) {
            System.out.println("字符串: " + str.toUpperCase());
        }
        
        // 不同类型的泛型集合
        List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
        List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
        
        System.out.println("整数列表: " + intList);
        System.out.println("浮点数列表: " + doubleList);
    }
    
    public static void demonstrateWildcards() {
        System.out.println("\n--- 通配符使用 ---");
        
        List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
        List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
        List<String> stringList = Arrays.asList("A", "B", "C");
        
        // 1. 无界通配符 ?
        printListSize(intList);
        printListSize(doubleList);
        printListSize(stringList);
        
        // 2. 上界通配符 ? extends
        System.out.println("数字列表求和:");
        System.out.println("整数和: " + sumNumbers(intList));
        System.out.println("浮点数和: " + sumNumbers(doubleList));
        
        // 3. 下界通配符 ? super
        List<Number> numberList = new ArrayList<>();
        addNumbers(numberList);
        System.out.println("添加数字后: " + numberList);
    }
    
    // 无界通配符:可以接受任何类型的List
    public static void printListSize(List<?> list) {
        System.out.println("列表大小: " + list.size() + ", 内容: " + list);
    }
    
    // 上界通配符:只能读取,不能添加(除了null)
    public static double sumNumbers(List<? extends Number> numbers) {
        double sum = 0.0;
        for (Number num : numbers) {
            sum += num.doubleValue();
        }
        return sum;
    }
    
    // 下界通配符:可以添加,但读取时只能当作Object
    public static void addNumbers(List<? super Integer> list) {
        list.add(10);
        list.add(20);
        list.add(30);
        // Integer item = list.get(0); // 编译错误
        Object item = list.get(0); // 只能当作Object读取
    }
    
    public static void demonstrateBoundedGenerics() {
        System.out.println("\n--- 有界泛型 ---");
        
        // 创建不同类型的容器
        NumberContainer<Integer> intContainer = new NumberContainer<>(42);
        NumberContainer<Double> doubleContainer = new NumberContainer<>(3.14);
        
        System.out.println("整数容器: " + intContainer.getValue());
        System.out.println("整数容器数值操作: " + intContainer.getDoubleValue());
        
        System.out.println("浮点容器: " + doubleContainer.getValue());
        System.out.println("浮点容器数值操作: " + doubleContainer.getDoubleValue());
        
        // 比较容器
        System.out.println("容器比较: " + intContainer.compareTo(doubleContainer));
    }
    
    // 有界泛型类:T必须是Number的子类
    static class NumberContainer<T extends Number> implements Comparable<NumberContainer<? extends Number>> {
        private T value;
        
        public NumberContainer(T value) {
            this.value = value;
        }
        
        public T getValue() {
            return value;
        }
        
        public double getDoubleValue() {
            return value.doubleValue();
        }
        
        @Override
        public int compareTo(NumberContainer<? extends Number> other) {
            return Double.compare(this.getDoubleValue(), other.getDoubleValue());
        }
        
        @Override
        public String toString() {
            return "NumberContainer{value=" + value + "}";
        }
    }
}

7.2 List接口和实现类

7.2.1 ArrayList详解

import java.util.*;
import java.util.function.Predicate;

/**
 * ArrayList详细演示
 */
public class ArrayListDemo {
    public static void main(String[] args) {
        System.out.println("=== ArrayList详细演示 ===");
        
        demonstrateBasicOperations();
        demonstrateAdvancedOperations();
        demonstratePerformanceCharacteristics();
        demonstrateCommonUseCases();
    }
    
    public static void demonstrateBasicOperations() {
        System.out.println("\n--- ArrayList基本操作 ---");
        
        // 1. 创建ArrayList
        List<String> fruits = new ArrayList<>();
        System.out.println("初始容量: " + fruits.size());
        
        // 指定初始容量
        List<String> vegetables = new ArrayList<>(20);
        
        // 从其他集合创建
        List<String> colors = new ArrayList<>(Arrays.asList("Red", "Green", "Blue"));
        System.out.println("从数组创建: " + colors);
        
        // 2. 添加元素
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");
        System.out.println("添加元素后: " + fruits);
        
        // 在指定位置插入
        fruits.add(1, "Apricot");
        System.out.println("在索引1插入Apricot: " + fruits);
        
        // 3. 访问元素
        System.out.println("\n访问元素:");
        System.out.println("第一个元素: " + fruits.get(0));
        System.out.println("最后一个元素: " + fruits.get(fruits.size() - 1));
        
        // 4. 修改元素
        fruits.set(2, "Coconut");
        System.out.println("修改索引2的元素: " + fruits);
        
        // 5. 查找元素
        System.out.println("\n查找元素:");
        System.out.println("Apple的索引: " + fruits.indexOf("Apple"));
        System.out.println("包含Banana: " + fruits.contains("Banana"));
        
        // 6. 删除元素
        fruits.remove("Apricot");
        System.out.println("删除Apricot: " + fruits);
        
        fruits.remove(0);
        System.out.println("删除索引0的元素: " + fruits);
    }
    
    public static void demonstrateAdvancedOperations() {
        System.out.println("\n--- ArrayList高级操作 ---");
        
        List<Integer> numbers = new ArrayList<>(Arrays.asList(5, 2, 8, 1, 9, 3));
        System.out.println("原始列表: " + numbers);
        
        // 1. 排序
        List<Integer> sortedNumbers = new ArrayList<>(numbers);
        Collections.sort(sortedNumbers);
        System.out.println("升序排序: " + sortedNumbers);
        
        Collections.sort(sortedNumbers, Collections.reverseOrder());
        System.out.println("降序排序: " + sortedNumbers);
        
        // 2. 查找
        Collections.sort(numbers); // 二分查找需要有序列表
        int index = Collections.binarySearch(numbers, 5);
        System.out.println("二分查找5的位置: " + index);
        
        // 3. 最大值和最小值
        System.out.println("最大值: " + Collections.max(numbers));
        System.out.println("最小值: " + Collections.min(numbers));
        
        // 4. 反转
        Collections.reverse(numbers);
        System.out.println("反转后: " + numbers);
        
        // 5. 打乱
        Collections.shuffle(numbers);
        System.out.println("打乱后: " + numbers);
        
        // 6. 子列表
        List<Integer> subList = numbers.subList(1, 4);
        System.out.println("子列表[1,4): " + subList);
        
        // 7. 批量操作
        List<Integer> evenNumbers = Arrays.asList(2, 4, 6, 8);
        numbers.retainAll(evenNumbers); // 保留交集
        System.out.println("保留偶数: " + numbers);
    }
    
    public static void demonstratePerformanceCharacteristics() {
        System.out.println("\n--- ArrayList性能特征 ---");
        
        List<Integer> list = new ArrayList<>();
        
        // 1. 添加性能测试
        long startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            list.add(i);
        }
        long endTime = System.nanoTime();
        System.out.println("添加100000个元素耗时: " + (endTime - startTime) / 1000000 + "ms");
        
        // 2. 随机访问性能
        Random random = new Random();
        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            int index = random.nextInt(list.size());
            list.get(index);
        }
        endTime = System.nanoTime();
        System.out.println("随机访问10000次耗时: " + (endTime - startTime) / 1000000 + "ms");
        
        // 3. 中间插入性能(相对较慢)
        startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            list.add(list.size() / 2, i);
        }
        endTime = System.nanoTime();
        System.out.println("中间插入1000个元素耗时: " + (endTime - startTime) / 1000000 + "ms");
        
        System.out.println("\nArrayList特点:");
        System.out.println("- 基于动态数组实现");
        System.out.println("- 随机访问速度快 O(1)");
        System.out.println("- 尾部添加速度快 O(1)");
        System.out.println("- 中间插入/删除较慢 O(n)");
        System.out.println("- 非线程安全");
    }
    
    public static void demonstrateCommonUseCases() {
        System.out.println("\n--- ArrayList常见用例 ---");
        
        // 1. 学生成绩管理
        List<Student> students = new ArrayList<>();
        students.add(new Student("张三", 85));
        students.add(new Student("李四", 92));
        students.add(new Student("王五", 78));
        students.add(new Student("赵六", 96));
        
        System.out.println("\n学生列表:");
        for (Student student : students) {
            System.out.println(student);
        }
        
        // 按成绩排序
        students.sort((s1, s2) -> Integer.compare(s2.getScore(), s1.getScore()));
        System.out.println("\n按成绩降序排序:");
        students.forEach(System.out::println);
        
        // 筛选高分学生
        List<Student> highScoreStudents = new ArrayList<>();
        for (Student student : students) {
            if (student.getScore() >= 90) {
                highScoreStudents.add(student);
            }
        }
        System.out.println("\n高分学生(>=90):");
        highScoreStudents.forEach(System.out::println);
        
        // 使用Stream API(更简洁)
        System.out.println("\n使用Stream筛选高分学生:");
        students.stream()
                .filter(s -> s.getScore() >= 90)
                .forEach(System.out::println);
        
        // 2. 动态数据收集
        List<String> userInputs = new ArrayList<>();
        Scanner scanner = new Scanner("apple\nbanana\ncherry\nquit");
        
        System.out.println("\n模拟用户输入收集:");
        String input;
        while (scanner.hasNext() && !(input = scanner.next()).equals("quit")) {
            userInputs.add(input);
            System.out.println("添加: " + input);
        }
        System.out.println("收集到的输入: " + userInputs);
        
        // 3. 缓存和临时存储
        List<String> cache = new ArrayList<>();
        
        // 模拟缓存操作
        addToCache(cache, "data1");
        addToCache(cache, "data2");
        addToCache(cache, "data3");
        
        System.out.println("\n缓存内容: " + cache);
        
        // 清理缓存
        cache.removeIf(item -> item.startsWith("data1"));
        System.out.println("清理后缓存: " + cache);
    }
    
    private static void addToCache(List<String> cache, String data) {
        cache.add(data);
        System.out.println("添加到缓存: " + data);
    }
    
    // 学生类
    static class Student {
        private String name;
        private int score;
        
        public Student(String name, int score) {
            this.name = name;
            this.score = score;
        }
        
        public String getName() {
            return name;
        }
        
        public int getScore() {
            return score;
        }
        
        @Override
        public String toString() {
            return String.format("Student{name='%s', score=%d}", name, score);
        }
    }
}

7.2.2 LinkedList详解

import java.util.*;

/**
 * LinkedList详细演示
 */
public class LinkedListDemo {
    public static void main(String[] args) {
        System.out.println("=== LinkedList详细演示 ===");
        
        demonstrateBasicOperations();
        demonstrateDequeOperations();
        demonstratePerformanceComparison();
        demonstrateUseCases();
    }
    
    public static void demonstrateBasicOperations() {
        System.out.println("\n--- LinkedList基本操作 ---");
        
        // 1. 创建LinkedList
        LinkedList<String> list = new LinkedList<>();
        
        // 2. 添加元素
        list.add("First");
        list.add("Second");
        list.add("Third");
        System.out.println("基本添加: " + list);
        
        // 3. 头部和尾部操作
        list.addFirst("New First");
        list.addLast("New Last");
        System.out.println("头尾添加后: " + list);
        
        // 4. 访问头部和尾部
        System.out.println("\n访问操作:");
        System.out.println("第一个元素: " + list.getFirst());
        System.out.println("最后一个元素: " + list.getLast());
        System.out.println("查看第一个元素: " + list.peekFirst());
        System.out.println("查看最后一个元素: " + list.peekLast());
        
        // 5. 删除操作
        System.out.println("\n删除操作:");
        String removedFirst = list.removeFirst();
        String removedLast = list.removeLast();
        System.out.println("删除的第一个元素: " + removedFirst);
        System.out.println("删除的最后一个元素: " + removedLast);
        System.out.println("删除后的列表: " + list);
        
        // 6. 中间操作
        list.add(1, "Inserted");
        System.out.println("在索引1插入: " + list);
        
        String element = list.get(1);
        System.out.println("获取索引1的元素: " + element);
        
        list.set(1, "Modified");
        System.out.println("修改索引1的元素: " + list);
    }
    
    public static void demonstrateDequeOperations() {
        System.out.println("\n--- LinkedList作为双端队列(Deque) ---");
        
        Deque<Integer> deque = new LinkedList<>();
        
        // 1. 队列操作 (FIFO)
        System.out.println("\n队列操作 (FIFO):");
        deque.offer(1); // 入队
        deque.offer(2);
        deque.offer(3);
        System.out.println("入队后: " + deque);
        
        while (!deque.isEmpty()) {
            System.out.println("出队: " + deque.poll());
        }
        
        // 2. 栈操作 (LIFO)
        System.out.println("\n栈操作 (LIFO):");
        deque.push(1); // 入栈
        deque.push(2);
        deque.push(3);
        System.out.println("入栈后: " + deque);
        
        while (!deque.isEmpty()) {
            System.out.println("出栈: " + deque.pop());
        }
        
        // 3. 双端操作
        System.out.println("\n双端操作:");
        deque.offerFirst(1);
        deque.offerLast(2);
        deque.offerFirst(0);
        deque.offerLast(3);
        System.out.println("双端添加后: " + deque);
        
        System.out.println("从前端移除: " + deque.pollFirst());
        System.out.println("从后端移除: " + deque.pollLast());
        System.out.println("剩余元素: " + deque);
    }
    
    public static void demonstratePerformanceComparison() {
        System.out.println("\n--- ArrayList vs LinkedList 性能比较 ---");
        
        int size = 100000;
        
        // 1. 顺序添加性能
        System.out.println("\n1. 顺序添加性能测试:");
        
        List<Integer> arrayList = new ArrayList<>();
        long startTime = System.nanoTime();
        for (int i = 0; i < size; i++) {
            arrayList.add(i);
        }
        long arrayListAddTime = System.nanoTime() - startTime;
        
        List<Integer> linkedList = new LinkedList<>();
        startTime = System.nanoTime();
        for (int i = 0; i < size; i++) {
            linkedList.add(i);
        }
        long linkedListAddTime = System.nanoTime() - startTime;
        
        System.out.println("ArrayList添加耗时: " + arrayListAddTime / 1000000 + "ms");
        System.out.println("LinkedList添加耗时: " + linkedListAddTime / 1000000 + "ms");
        
        // 2. 随机访问性能
        System.out.println("\n2. 随机访问性能测试:");
        Random random = new Random();
        
        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            arrayList.get(random.nextInt(arrayList.size()));
        }
        long arrayListGetTime = System.nanoTime() - startTime;
        
        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            linkedList.get(random.nextInt(linkedList.size()));
        }
        long linkedListGetTime = System.nanoTime() - startTime;
        
        System.out.println("ArrayList随机访问耗时: " + arrayListGetTime / 1000000 + "ms");
        System.out.println("LinkedList随机访问耗时: " + linkedListGetTime / 1000000 + "ms");
        
        // 3. 头部插入性能
        System.out.println("\n3. 头部插入性能测试:");
        
        List<Integer> arrayListInsert = new ArrayList<>();
        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            arrayListInsert.add(0, i);
        }
        long arrayListInsertTime = System.nanoTime() - startTime;
        
        LinkedList<Integer> linkedListInsert = new LinkedList<>();
        startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            linkedListInsert.addFirst(i);
        }
        long linkedListInsertTime = System.nanoTime() - startTime;
        
        System.out.println("ArrayList头部插入耗时: " + arrayListInsertTime / 1000000 + "ms");
        System.out.println("LinkedList头部插入耗时: " + linkedListInsertTime / 1000000 + "ms");
        
        System.out.println("\n性能总结:");
        System.out.println("ArrayList: 随机访问快,中间插入慢");
        System.out.println("LinkedList: 头尾操作快,随机访问慢");
    }
    
    public static void demonstrateUseCases() {
        System.out.println("\n--- LinkedList适用场景 ---");
        
        // 1. 实现LRU缓存
        System.out.println("\n1. LRU缓存实现:");
        LRUCache<String, String> cache = new LRUCache<>(3);
        
        cache.put("key1", "value1");
        cache.put("key2", "value2");
        cache.put("key3", "value3");
        System.out.println("添加3个元素: " + cache);
        
        cache.get("key1"); // 访问key1,使其成为最近使用
        cache.put("key4", "value4"); // 添加新元素,应该移除key2
        System.out.println("访问key1后添加key4: " + cache);
        
        // 2. 撤销/重做功能
        System.out.println("\n2. 撤销/重做功能:");
        UndoRedoManager<String> undoRedo = new UndoRedoManager<>();
        
        undoRedo.execute("操作1");
        undoRedo.execute("操作2");
        undoRedo.execute("操作3");
        System.out.println("执行3个操作后: " + undoRedo.getCurrentState());
        
        undoRedo.undo();
        System.out.println("撤销一次: " + undoRedo.getCurrentState());
        
        undoRedo.redo();
        System.out.println("重做一次: " + undoRedo.getCurrentState());
        
        // 3. 音乐播放列表
        System.out.println("\n3. 音乐播放列表:");
        MusicPlaylist playlist = new MusicPlaylist();
        
        playlist.addSong("Song 1");
        playlist.addSong("Song 2");
        playlist.addSong("Song 3");
        
        System.out.println("当前播放: " + playlist.getCurrentSong());
        System.out.println("下一首: " + playlist.nextSong());
        System.out.println("上一首: " + playlist.previousSong());
        
        playlist.shuffle();
        System.out.println("随机播放后: " + playlist.getCurrentSong());
    }
    
    // 简单的LRU缓存实现
    static class LRUCache<K, V> {
        private final int capacity;
        private final LinkedList<Node<K, V>> list;
        private final Map<K, Node<K, V>> map;
        
        public LRUCache(int capacity) {
            this.capacity = capacity;
            this.list = new LinkedList<>();
            this.map = new HashMap<>();
        }
        
        public V get(K key) {
            Node<K, V> node = map.get(key);
            if (node == null) {
                return null;
            }
            
            // 移动到头部
            list.remove(node);
            list.addFirst(node);
            
            return node.value;
        }
        
        public void put(K key, V value) {
            Node<K, V> existingNode = map.get(key);
            
            if (existingNode != null) {
                // 更新现有节点
                existingNode.value = value;
                list.remove(existingNode);
                list.addFirst(existingNode);
            } else {
                // 添加新节点
                Node<K, V> newNode = new Node<>(key, value);
                
                if (list.size() >= capacity) {
                    // 移除最少使用的节点
                    Node<K, V> last = list.removeLast();
                    map.remove(last.key);
                }
                
                list.addFirst(newNode);
                map.put(key, newNode);
            }
        }
        
        @Override
        public String toString() {
            return list.toString();
        }
        
        static class Node<K, V> {
            K key;
            V value;
            
            Node(K key, V value) {
                this.key = key;
                this.value = value;
            }
            
            @Override
            public String toString() {
                return key + "=" + value;
            }
        }
    }
    
    // 撤销/重做管理器
    static class UndoRedoManager<T> {
        private LinkedList<T> undoStack = new LinkedList<>();
        private LinkedList<T> redoStack = new LinkedList<>();
        private T currentState;
        
        public void execute(T newState) {
            if (currentState != null) {
                undoStack.push(currentState);
            }
            currentState = newState;
            redoStack.clear(); // 执行新操作后清空重做栈
        }
        
        public boolean undo() {
            if (undoStack.isEmpty()) {
                return false;
            }
            
            if (currentState != null) {
                redoStack.push(currentState);
            }
            currentState = undoStack.pop();
            return true;
        }
        
        public boolean redo() {
            if (redoStack.isEmpty()) {
                return false;
            }
            
            if (currentState != null) {
                undoStack.push(currentState);
            }
            currentState = redoStack.pop();
            return true;
        }
        
        public T getCurrentState() {
            return currentState;
        }
    }
    
    // 音乐播放列表
    static class MusicPlaylist {
        private LinkedList<String> songs = new LinkedList<>();
        private int currentIndex = -1;
        
        public void addSong(String song) {
            songs.add(song);
            if (currentIndex == -1) {
                currentIndex = 0;
            }
        }
        
        public String getCurrentSong() {
            if (songs.isEmpty() || currentIndex < 0) {
                return null;
            }
            return songs.get(currentIndex);
        }
        
        public String nextSong() {
            if (songs.isEmpty()) {
                return null;
            }
            currentIndex = (currentIndex + 1) % songs.size();
            return getCurrentSong();
        }
        
        public String previousSong() {
            if (songs.isEmpty()) {
                return null;
            }
            currentIndex = (currentIndex - 1 + songs.size()) % songs.size();
            return getCurrentSong();
        }
        
        public void shuffle() {
            Collections.shuffle(songs);
            currentIndex = 0;
        }
    }
}

7.2.3 Vector和ArrayList的比较

import java.util.*;
import java.util.concurrent.*;

/**
 * Vector和ArrayList比较演示
 */
public class VectorVsArrayListDemo {
    public static void main(String[] args) {
        System.out.println("=== Vector vs ArrayList 比较 ===");
        
        demonstrateBasicDifferences();
        demonstrateThreadSafety();
        demonstratePerformance();
        demonstrateAlternatives();
    }
    
    public static void demonstrateBasicDifferences() {
        System.out.println("\n--- 基本差异 ---");
        
        // 1. 创建方式相同
        Vector<String> vector = new Vector<>();
        ArrayList<String> arrayList = new ArrayList<>();
        
        // 2. 基本操作相同
        vector.add("Vector Element");
        arrayList.add("ArrayList Element");
        
        System.out.println("Vector: " + vector);
        System.out.println("ArrayList: " + arrayList);
        
        // 3. Vector特有的方法
        vector.addElement("Old Style Add"); // 旧式方法
        System.out.println("Vector特有方法: " + vector);
        
        // 4. 容量管理
        System.out.println("\n容量管理:");
        System.out.println("Vector初始容量: " + vector.capacity());
        
        // ArrayList没有capacity()方法
        // System.out.println("ArrayList初始容量: " + arrayList.capacity()); // 编译错误
        
        // 5. 增长策略
        System.out.println("\n增长策略差异:");
        System.out.println("Vector: 每次增长100%(翻倍)");
        System.out.println("ArrayList: 每次增长50%");
        
        demonstrateGrowthStrategy();
    }
    
    private static void demonstrateGrowthStrategy() {
        // 观察Vector的增长
        Vector<Integer> vector = new Vector<>(2);
        System.out.println("\nVector增长过程:");
        System.out.println("初始容量: " + vector.capacity());
        
        for (int i = 0; i < 10; i++) {
            vector.add(i);
            System.out.println("添加元素" + i + "后容量: " + vector.capacity());
        }
    }
    
    public static void demonstrateThreadSafety() {
        System.out.println("\n--- 线程安全性演示 ---");
        
        Vector<Integer> vector = new Vector<>();
        ArrayList<Integer> arrayList = new ArrayList<>();
        
        // 线程安全测试
        int threadCount = 10;
        int operationsPerThread = 1000;
        
        // 测试Vector(线程安全)
        System.out.println("\n测试Vector线程安全性:");
        testConcurrentAccess(vector, threadCount, operationsPerThread, "Vector");
        
        // 测试ArrayList(非线程安全)
        System.out.println("\n测试ArrayList线程安全性:");
        testConcurrentAccess(arrayList, threadCount, operationsPerThread, "ArrayList");
        
        // 使用同步包装器
        System.out.println("\n使用同步包装器:");
        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        testConcurrentAccess(synchronizedList, threadCount, operationsPerThread, "SynchronizedList");
    }
    
    private static void testConcurrentAccess(List<Integer> list, int threadCount, 
                                           int operationsPerThread, String listType) {
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            executor.submit(() -> {
                try {
                    for (int j = 0; j < operationsPerThread; j++) {
                        list.add(threadId * operationsPerThread + j);
                    }
                } finally {
                    latch.countDown();
                }
            });
        }
        
        try {
            latch.await();
            long endTime = System.currentTimeMillis();
            
            System.out.println(listType + " 结果:");
            System.out.println("  期望大小: " + (threadCount * operationsPerThread));
            System.out.println("  实际大小: " + list.size());
            System.out.println("  耗时: " + (endTime - startTime) + "ms");
            System.out.println("  数据完整性: " + 
                             (list.size() == threadCount * operationsPerThread ? "正确" : "错误"));
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            executor.shutdown();
        }
    }
    
    public static void demonstratePerformance() {
        System.out.println("\n--- 性能比较 ---");
        
        int size = 1000000;
        
        // 1. 添加性能
        System.out.println("\n1. 添加性能测试:");
        
        Vector<Integer> vector = new Vector<>();
        long startTime = System.nanoTime();
        for (int i = 0; i < size; i++) {
            vector.add(i);
        }
        long vectorTime = System.nanoTime() - startTime;
        
        ArrayList<Integer> arrayList = new ArrayList<>();
        startTime = System.nanoTime();
        for (int i = 0; i < size; i++) {
            arrayList.add(i);
        }
        long arrayListTime = System.nanoTime() - startTime;
        
        System.out.println("Vector添加耗时: " + vectorTime / 1000000 + "ms");
        System.out.println("ArrayList添加耗时: " + arrayListTime / 1000000 + "ms");
        System.out.println("ArrayList比Vector快: " + 
                         String.format("%.2f", (double) vectorTime / arrayListTime) + "倍");
        
        // 2. 访问性能
        System.out.println("\n2. 随机访问性能测试:");
        Random random = new Random();
        
        startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            vector.get(random.nextInt(vector.size()));
        }
        long vectorGetTime = System.nanoTime() - startTime;
        
        startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            arrayList.get(random.nextInt(arrayList.size()));
        }
        long arrayListGetTime = System.nanoTime() - startTime;
        
        System.out.println("Vector访问耗时: " + vectorGetTime / 1000000 + "ms");
        System.out.println("ArrayList访问耗时: " + arrayListGetTime / 1000000 + "ms");
        
        System.out.println("\n性能差异原因:");
        System.out.println("- Vector的所有方法都是synchronized的");
        System.out.println("- 同步开销导致性能下降");
        System.out.println("- 单线程环境下ArrayList更优");
    }
    
    public static void demonstrateAlternatives() {
        System.out.println("\n--- 现代替代方案 ---");
        
        // 1. CopyOnWriteArrayList - 读多写少场景
        System.out.println("\n1. CopyOnWriteArrayList (读多写少):");
        CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
        cowList.add("Item 1");
        cowList.add("Item 2");
        
        // 迭代过程中修改不会抛出异常
        for (String item : cowList) {
            System.out.println("读取: " + item);
            if ("Item 1".equals(item)) {
                cowList.add("Item 3"); // 安全的并发修改
            }
        }
        System.out.println("最终内容: " + cowList);
        
        // 2. Collections.synchronizedList
        System.out.println("\n2. Collections.synchronizedList:");
        List<String> syncList = Collections.synchronizedList(new ArrayList<>());
        syncList.add("Sync Item 1");
        syncList.add("Sync Item 2");
        
        // 注意:迭代时仍需要手动同步
        synchronized (syncList) {
            for (String item : syncList) {
                System.out.println("同步访问: " + item);
            }
        }
        
        // 3. 使用并发集合
        System.out.println("\n3. 并发集合推荐:");
        System.out.println("- ConcurrentLinkedQueue: 并发队列");
        System.out.println("- CopyOnWriteArrayList: 读多写少的列表");
        System.out.println("- ConcurrentHashMap: 并发Map");
        
        System.out.println("\n选择建议:");
        System.out.println("- 单线程: 使用ArrayList");
        System.out.println("- 多线程读多写少: 使用CopyOnWriteArrayList");
        System.out.println("- 多线程频繁写: 使用ConcurrentLinkedQueue");
        System.out.println("- 需要同步的List: 使用Collections.synchronizedList");
        System.out.println("- 避免使用Vector(除非维护遗留代码)");
    }
}

本章小结

本章详细介绍了Java集合框架的核心内容:

集合框架概述:

  • Collection和Map接口层次结构
  • 泛型在集合中的应用
  • 通配符和有界泛型的使用

List接口实现:

  • ArrayList:基于动态数组,随机访问快,适合读多写少
  • LinkedList:基于双向链表,头尾操作快,适合频繁插入删除
  • Vector:同步的ArrayList,性能较差,现代开发中较少使用

性能特征:

  • ArrayList:O(1)随机访问,O(n)中间插入
  • LinkedList:O(1)头尾操作,O(n)随机访问
  • Vector:同步开销导致性能下降

使用场景:

  • 数据存储和检索
  • 缓存实现
  • 撤销/重做功能
  • 播放列表等动态列表

下一章预告

下一章我们将继续学习Set接口和Map接口的实现类,包括HashSet、TreeSet、HashMap、TreeMap等。

练习题

  1. 实现一个支持撤销操作的文本编辑器
  2. 创建一个学生成绩管理系统,支持排序和筛选
  3. 实现一个简单的LRU缓存
  4. 比较ArrayList和LinkedList在不同场景下的性能