跳转至

集合框架

📖 章节简介

本章将介绍Java的集合框架,包括List、Set、Map等常用集合类的使用。

Java集合框架关系图

上图展示了 Collection 体系与 Map 体系的核心分支及典型实现类。

📋 List接口

1. ArrayList

Java
// ArrayList使用
import java.util.ArrayList;
import java.util.List;

public class ArrayListExample {
    public static void main(String[] args) {
        // 创建ArrayList
        List<String> fruits = new ArrayList<>();

        // 添加元素
        fruits.add("苹果");
        fruits.add("香蕉");
        fruits.add("橙子");

        // 在指定位置添加
        fruits.add(1, "葡萄");

        // 添加所有元素
        List<String> moreFruits = new ArrayList<>();
        moreFruits.add("西瓜");
        moreFruits.add("草莓");
        fruits.addAll(moreFruits);

        // 访问元素
        System.out.println("第一个水果: " + fruits.get(0));
        System.out.println("第二个水果: " + fruits.get(1));

        // 修改元素
        fruits.set(0, "红苹果");

        // 删除元素
        fruits.remove("香蕉");
        fruits.remove(2);  // 删除索引为2的元素

        // 遍历ArrayList
        System.out.println("\n遍历ArrayList:");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }

        // 获取大小
        System.out.println("\n水果数量: " + fruits.size());

        // 检查是否包含
        System.out.println("包含苹果: " + fruits.contains("苹果"));

        // 获取索引
        System.out.println("苹果的位置: " + fruits.indexOf("苹果"));

        // 清空列表
        fruits.clear();
        System.out.println("\n清空后的大小: " + fruits.size());
    }
}

2. LinkedList

Java
// LinkedList使用
import java.util.LinkedList;
import java.util.List;

public class LinkedListExample {
    public static void main(String[] args) {
        // 创建LinkedList
        List<Integer> numbers = new LinkedList<>();

        // 添加元素
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);

        // 在头部添加
        ((LinkedList<Integer>) numbers).addFirst(5);

        // 在尾部添加
        ((LinkedList<Integer>) numbers).addLast(40);

        // 获取头尾元素
        System.out.println("头元素: " + ((LinkedList<Integer>) numbers).getFirst());
        System.out.println("尾元素: " + ((LinkedList<Integer>) numbers).getLast());

        // 删除头尾元素
        ((LinkedList<Integer>) numbers).removeFirst();
        ((LinkedList<Integer>) numbers).removeLast();

        // 遍历LinkedList
        System.out.println("\n遍历LinkedList:");
        for (Integer num : numbers) {
            System.out.println(num);
        }
    }
}

🎯 Set接口

1. HashSet

Java
// HashSet使用
import java.util.HashSet;
import java.util.Set;

public class HashSetExample {
    public static void main(String[] args) {
        // 创建HashSet
        Set<String> names = new HashSet<>();

        // 添加元素
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("张三");  // 重复元素不会被添加

        // 遍历Set
        System.out.println("遍历HashSet:");
        for (String name : names) {
            System.out.println(name);
        }

        // 获取大小
        System.out.println("\n名字数量: " + names.size());

        // 检查是否包含
        System.out.println("包含张三: " + names.contains("张三"));

        // 删除元素
        names.remove("李四");

        // 清空Set
        names.clear();
        System.out.println("\n清空后的大小: " + names.size());
    }
}

2. TreeSet

Java
// TreeSet使用
import java.util.TreeSet;
import java.util.Set;

public class TreeSetExample {
    public static void main(String[] args) {
        // 创建TreeSet(自动排序)
        Set<Integer> numbers = new TreeSet<>();

        // 添加元素
        numbers.add(30);
        numbers.add(10);
        numbers.add(20);
        numbers.add(40);
        numbers.add(10);  // 重复元素不会被添加

        // 遍历TreeSet(已排序)
        System.out.println("遍历TreeSet:");
        for (Integer num : numbers) {
            System.out.println(num);
        }

        // 获取第一个和最后一个元素
        System.out.println("\n第一个元素: " + ((TreeSet<Integer>) numbers).first());
        System.out.println("最后一个元素: " + ((TreeSet<Integer>) numbers).last());

        // 获取子集
        System.out.println("\n小于30的元素: " + ((TreeSet<Integer>) numbers).headSet(30));
        System.out.println("大于等于20的元素: " + ((TreeSet<Integer>) numbers).tailSet(20));
    }
}

🗺️ Map接口

1. HashMap

Java
// HashMap使用
import java.util.HashMap;
import java.util.Map;

public class HashMapExample {
    public static void main(String[] args) {
        // 创建HashMap
        Map<String, Integer> scores = new HashMap<>();

        // 添加键值对
        scores.put("张三", 95);
        scores.put("李四", 87);
        scores.put("王五", 92);
        scores.put("赵六", 88);

        // 获取值
        System.out.println("张三的分数: " + scores.get("张三"));
        System.out.println("李四的分数: " + scores.get("李四"));

        // 修改值
        scores.put("张三", 98);

        // 删除键值对
        scores.remove("赵六");

        // 检查是否包含键
        System.out.println("\n包含张三: " + scores.containsKey("张三"));
        System.out.println("包含分数95: " + scores.containsValue(95));

        // 遍历Map
        System.out.println("\n遍历HashMap:");
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        // 获取所有键
        System.out.println("\n所有键: " + scores.keySet());

        // 获取所有值
        System.out.println("所有值: " + scores.values());

        // 获取大小
        System.out.println("\n键值对数量: " + scores.size());

        // 清空Map
        scores.clear();
        System.out.println("\n清空后的大小: " + scores.size());
    }
}

2. TreeMap

Java
// TreeMap使用
import java.util.TreeMap;
import java.util.Map;

public class TreeMapExample {
    public static void main(String[] args) {
        // 创建TreeMap(按键排序)
        Map<String, String> dictionary = new TreeMap<>();

        // 添加键值对
        dictionary.put("apple", "苹果");
        dictionary.put("banana", "香蕉");
        dictionary.put("orange", "橙子");
        dictionary.put("grape", "葡萄");

        // 遍历TreeMap(按键排序)
        System.out.println("遍历TreeMap:");
        for (Map.Entry<String, String> entry : dictionary.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        // 获取第一个和最后一个键
        System.out.println("\n第一个键: " + ((TreeMap<String, String>) dictionary).firstKey());
        System.out.println("最后一个键: " + ((TreeMap<String, String>) dictionary).lastKey());

        // 获取子Map
        System.out.println("\n小于'orange'的键: " + ((TreeMap<String, String>) dictionary).headMap("orange"));
        System.out.println("大于等于'orange'的键: " + ((TreeMap<String, String>) dictionary).tailMap("orange"));
    }
}

🔄 迭代器

1. Iterator

Java
// Iterator使用
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("张三");
        names.add("李四");
        names.add("王五");

        // 使用Iterator遍历
        System.out.println("使用Iterator遍历:");
        Iterator<String> iterator = names.iterator();
        while (iterator.hasNext()) {
            String name = iterator.next();
            System.out.println(name);

            // 删除元素
            if (name.equals("李四")) {
                iterator.remove();
            }
        }

        // 遍历删除后的List
        System.out.println("\n删除后遍历:");
        for (String name : names) {
            System.out.println(name);
        }
    }
}

2. ListIterator

Java
// ListIterator使用
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.List;

public class ListIteratorExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);

        // 使用ListIterator双向遍历
        System.out.println("正向遍历:");
        ListIterator<Integer> iterator = numbers.listIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        System.out.println("\n反向遍历:");
        while (iterator.hasPrevious()) {
            System.out.println(iterator.previous());
        }

        // 在遍历时添加元素
        iterator = numbers.listIterator();
        while (iterator.hasNext()) {
            Integer num = iterator.next();
            if (num == 30) {
                iterator.add(35);  // 在30后面添加35
            }
        }

        System.out.println("\n添加后遍历:");
        for (Integer num : numbers) {
            System.out.println(num);
        }
    }
}

💡 最佳实践

1. 集合选择

Java
// 集合选择指南
public class CollectionSelection {
    /*
    List选择:
    - 需要快速访问元素:ArrayList
    - 需要频繁插入删除:LinkedList
    - 需要线程安全:Vector, CopyOnWriteArrayList

    Set选择:
    - 需要快速查找:HashSet
    - 需要排序:TreeSet
    - 需要保持插入顺序:LinkedHashSet

    Map选择:
    - 需要快速查找:HashMap
    - 需要排序:TreeMap
    - 需要保持插入顺序:LinkedHashMap
    */
}

2. 性能优化

Java
// 集合性能优化
public class CollectionOptimization {
    public static void main(String[] args) {
        // ✅ 好的做法:指定初始容量
        List<String> list = new ArrayList<>(1000);

        // ❌ 不好的做法:不指定初始容量
        List<String> list2 = new ArrayList<>();

        // ✅ 好的做法:使用增强for循环
        for (String item : list) {
            System.out.println(item);
        }

        // ❌ 不好的做法:使用索引访问LinkedList
        // for (int i = 0; i < linkedList.size(); i++) {
        //     linkedList.get(i);  // 性能差
        // }
    }
}

📝 练习题

基础题

  1. List、Set、Map有什么区别?
  2. ArrayList和LinkedList有什么区别?
  3. 如何遍历集合?

进阶题

  1. 实现自定义集合类。
  2. 使用泛型提高类型安全。
  3. 优化集合性能。

实践题

  1. 创建一个学生管理系统。
  2. 实现一个简单的缓存系统。
  3. 构建一个单词统计工具。

📚 推荐阅读

🔗 下一章

IO流 - 学习Java的IO流操作。