集合是Java处理数据的利器,掌握它就是掌握数据管理的艺术。

目录


1. 集合框架概览

Java集合框架主要分为三大接口:

1.1 Collection接口

Collection
├── List(有序,可重复)
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector
├── Set(无序,不可重复)
│   ├── HashSet
│   ├── LinkedHashSet
│   └── TreeSet
└── Queue(队列)
    ├── LinkedList
    ├── PriorityQueue
    └── ArrayDeque

1.2 Map接口

Map(键值对)
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable

1.3 如何选择集合?

需求 推荐集合
有序,可重复 ArrayList
频繁插入/删除 LinkedList
去重 HashSet
有序去重 LinkedHashSet
排序 TreeSet
键值对 HashMap
键需要排序 TreeMap

2. List集合

List是有序的集合,元素可以重复。

2.1 ArrayList

基于动态数组实现,随机访问快,插入删除慢:

import java.util.ArrayList;
import java.util.List;

public class ArrayListDemo {
    public static void main(String[] args) {
        // 创建ArrayList
        List<String> fruits = new ArrayList<>();
        
        // 添加元素
        fruits.add("苹果");
        fruits.add("香蕉");
        fruits.add("橙子");
        fruits.add("葡萄");
        fruits.add("苹果");  // 可以重复
        
        System.out.println("水果列表:" + fruits);
        System.out.println("元素数量:" + fruits.size());
        
        // 访问元素
        System.out.println("第一个:" + fruits.get(0));
        System.out.println("最后一个:" + fruits.get(fruits.size() - 1));
        
        // 修改元素
        fruits.set(1, "西瓜");
        System.out.println("修改后:" + fruits);
        
        // 删除元素
        fruits.remove("橙子");  // 按值删除
        fruits.remove(0);       // 按索引删除
        System.out.println("删除后:" + fruits);
        
        // 查找元素
        System.out.println("包含苹果:" + fruits.contains("苹果"));
        System.out.println("香蕉的位置:" + fruits.indexOf("香蕉"));
        
        // 遍历
        System.out.println("遍历方式1:");
        for (String fruit : fruits) {
            System.out.println("  " + fruit);
        }
        
        System.out.println("遍历方式2:");
        for (int i = 0; i < fruits.size(); i++) {
            System.out.println("  " + i + ": " + fruits.get(i));
        }
    }
}

2.2 LinkedList

基于双向链表实现,插入删除快,随机访问慢:

import java.util.LinkedList;

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        
        // 添加元素
        list.add("A");
        list.add("B");
        list.add("C");
        list.addFirst("X");  // 添加到开头
        list.addLast("Z");   // 添加到末尾
        
        System.out.println("列表:" + list);
        
        // 访问元素
        System.out.println("第一个:" + list.getFirst());
        System.out.println("最后一个:" + list.getLast());
        
        // 删除元素
        list.removeFirst();
        list.removeLast();
        System.out.println("删除后:" + list);
    }
}

2.3 ArrayList vs LinkedList

操作 ArrayList LinkedList
随机访问 O(1) O(n)
尾部添加 O(1) O(1)
中间插入 O(n) O(1)
中间删除 O(n) O(1)
内存占用 多(指针开销)

3. Set集合

Set是无序的集合,元素不能重复。

3.1 HashSet

基于哈希表实现,无序,不重复:

import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    public static void main(String[] args) {
        Set<String> colors = new HashSet<>();
        
        // 添加元素
        colors.add("红色");
        colors.add("蓝色");
        colors.add("绿色");
        colors.add("黄色");
        colors.add("红色");  // 重复,不会添加
        
        System.out.println("颜色集合:" + colors);
        System.out.println("元素数量:" + colors.size());
        
        // 判断是否包含
        System.out.println("包含红色:" + colors.contains("红色"));
        System.out.println("包含紫色:" + colors.contains("紫色"));
        
        // 删除元素
        colors.remove("蓝色");
        System.out.println("删除后:" + colors);
        
        // 遍历
        for (String color : colors) {
            System.out.println("  " + color);
        }
        
        // 去重应用
        List<Integer> numbers = List.of(1, 2, 3, 2, 1, 4, 3, 5);
        Set<Integer> uniqueNumbers = new HashSet<>(numbers);
        System.out.println("去重前:" + numbers);
        System.out.println("去重后:" + uniqueNumbers);
    }
}

3.2 TreeSet

有序的Set,基于红黑树实现:

import java.util.TreeSet;
import java.util.Set;

public class TreeSetDemo {
    public static void main(String[] args) {
        Set<Integer> numbers = new TreeSet<>();
        
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);
        numbers.add(3);
        
        // 自动排序
        System.out.println("排序后的数字:" + numbers);
        // 输出:[1, 2, 3, 5, 8]
    }
}

3.3 Set的选择

Set类型 底层结构 特点 适用场景
HashSet 哈希表 无序,最快 去重,不关心顺序
LinkedHashSet 哈希表+链表 保持插入顺序 需要保持顺序的去重
TreeSet 红黑树 有序(自然排序) 需要排序的去重

4. Map集合

Map是键值对集合,键不能重复。

4.1 HashMap

基于哈希表实现,无序:

import java.util.HashMap;
import java.util.Map;

public class HashMapDemo {
    public static void main(String[] args) {
        Map<String, Integer> scores = new HashMap<>();
        
        // 添加键值对
        scores.put("张三", 85);
        scores.put("李四", 92);
        scores.put("王五", 78);
        scores.put("赵六", 95);
        
        System.out.println("成绩表:" + scores);
        
        // 访问值
        System.out.println("张三的成绩:" + scores.get("张三"));
        System.out.println("孙七的成绩:" + scores.getOrDefault("孙七", 0));
        
        // 修改值
        scores.put("张三", 88);
        System.out.println("修改后张三的成绩:" + scores.get("张三"));
        
        // 删除键值对
        scores.remove("王五");
        System.out.println("删除后:" + scores);
        
        // 判断是否存在
        System.out.println("包含李四:" + scores.containsKey("李四"));
        System.out.println("包含100分:" + scores.containsValue(100));
        
        // 遍历
        System.out.println("遍历方式1:");
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            System.out.println("  " + entry.getKey() + ":" + entry.getValue());
        }
        
        System.out.println("遍历方式2:");
        scores.forEach((name, score) -> {
            System.out.println("  " + name + ":" + score);
        });
    }
}

4.2 Map的选择

Map类型 底层结构 特点 适用场景
HashMap 哈希表 无序,最快 一般键值对存储
LinkedHashMap 哈希表+链表 保持插入顺序 需要保持顺序
TreeMap 红黑树 按键排序 需要按键排序
Hashtable 哈希表 线程安全,慢 遗留代码

5. 集合的高级操作

5.1 Collections工具类

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsDemo {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);
        numbers.add(3);
        
        System.out.println("原始列表:" + numbers);
        
        // 排序
        Collections.sort(numbers);
        System.out.println("排序后:" + numbers);
        
        // 反转
        Collections.reverse(numbers);
        System.out.println("反转后:" + numbers);
        
        // 打乱
        Collections.shuffle(numbers);
        System.out.println("打乱后:" + numbers);
        
        // 最大值和最小值
        System.out.println("最大值:" + Collections.max(numbers));
        System.out.println("最小值:" + Collections.min(numbers));
        
        // 不可变集合
        List<String> immutableList = Collections.unmodifiableList(
            List.of("A", "B", "C")
        );
        // immutableList.add("D");  // 抛出UnsupportedOperationException
    }
}

5.2 List转数组,数组转List

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ConversionDemo {
    public static void main(String[] args) {
        // 数组转List
        String[] array = {"A", "B", "C"};
        List<String> list = new ArrayList<>(Arrays.asList(array));
        System.out.println("数组转List:" + list);
        
        // List转数组
        String[] newArray = list.toArray(new String[0]);
        System.out.println("List转数组:" + Arrays.toString(newArray));
    }
}

6. 实战案例

6.1 单词统计

import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class WordCounter {
    public static void main(String[] args) {
        String text = "Java is great and Java is popular Java is everywhere";
        
        Map<String, Integer> wordCount = new HashMap<>();
        
        // 统计单词
        StringTokenizer tokenizer = new StringTokenizer(text.toLowerCase());
        while (tokenizer.hasMoreTokens()) {
            String word = tokenizer.nextToken();
            wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
        }
        
        // 输出结果
        System.out.println("=== 单词统计 ===");
        wordCount.forEach((word, count) -> {
            System.out.println(word + ":" + count + "次");
        });
        
        // 找出出现最多的单词
        String mostCommon = wordCount.entrySet().stream()
            .max(Map.Entry.comparingByValue())
            .map(Map.Entry::getKey)
            .orElse("");
        
        System.out.println("\n出现最多的单词:" + mostCommon + 
            "(" + wordCount.get(mostCommon) + "次)");
    }
}

7. 总结

本篇我们学习了:

List:ArrayList、LinkedList的使用和区别
Set:HashSet、LinkedHashSet、TreeSet的特点
Map:HashMap、LinkedHashMap、TreeMap的应用
Collections工具类:排序、查找、反转等操作
集合转换:数组与集合的互转

核心要点:

  1. 根据需求选择合适的集合类型
  2. ArrayList适合随机访问,LinkedList适合频繁插入删除
  3. HashSet最快但无序,TreeSet有序但较慢
  4. HashMap是键值对的首选,TreeMap需要按键排序

下一篇预告: 《Java从零到熟练(七):异常处理与I/O》

  • 学习异常处理机制
  • 掌握try-catch-finally
  • 了解文件读写操作

参考资源

  1. Java集合框架教程
  2. Java API文档 - java.util
  3. 廖雪峰Java教程 - 集合

下一篇: Java从零到熟练(七):异常处理与I/O

更多推荐