Java集合框架终极指南:从基础到高级应用

一、Java集合框架概述

Java集合框架(Java Collections Framework)是Java语言中用于存储和操作数据集合的一组接口和类。它提供了一套标准化的工具来处理各种数据结构,如列表、集合、队列和映射等。

1.1 集合框架的层次结构

Java集合框架主要分为两大类:

  • Collection接口:表示一组对象

    • List:有序可重复集合
    • Set:无序不可重复集合
    • Queue:队列,先进先出(FIFO)结构
  • Map接口:键值对映射

    • 不是Collection的子接口,但属于集合框架的一部分
// 集合框架简单示例
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");

Map<String, Integer> fruitPrices = new HashMap<>();
fruitPrices.put("Apple", 5);
fruitPrices.put("Banana", 3);
fruitPrices.put("Orange", 4);

1.2 集合框架的核心接口

接口描述主要实现类
List有序集合(序列),允许重复元素ArrayList, LinkedList, Vector, Stack
Set不包含重复元素的集合HashSet, LinkedHashSet, TreeSet
Queue用于在处理前保存元素的集合,通常但不一定按FIFO原则排序LinkedList, PriorityQueue, ArrayDeque
Deque双端队列,支持在两端插入和移除元素ArrayDeque, LinkedList
Map键值对映射,键不可重复HashMap, LinkedHashMap, TreeMap
SortedSet按升序维护其元素的SetTreeSet
SortedMap按升序维护其键的MapTreeMap

二、List接口及其实现类

2.1 ArrayList vs LinkedList

特性ArrayListLinkedList
底层数据结构动态数组双向链表
随机访问性能O(1) - 快O(n) - 慢
插入/删除性能O(n) - 慢(除非在末尾)O(1) - 快
内存占用较少(仅存储数据)较多(存储数据和前后节点引用)
适用场景频繁随机访问频繁插入删除
// ArrayList示例
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
arrayList.add(1, "C++"); // 在索引1处插入

// LinkedList示例
List<String> linkedList = new LinkedList<>();
linkedList.add("Apple");
linkedList.addFirst("Banana"); // 在头部添加
linkedList.addLast("Orange");  // 在尾部添加

2.2 Vector vs ArrayList

特性VectorArrayList
同步性线程安全非线程安全
扩容策略默认增长一倍增长50%
性能较慢(同步开销)较快
迭代器fail-fastfail-fast
遗留类
// Vector示例 - 线程安全但性能较低
Vector<String> vector = new Vector<>();
vector.add("Red");
vector.add("Green");
vector.add("Blue");

// 多线程环境下安全
synchronized(vector) {
    for (String color : vector) {
        System.out.println(color);
    }
}

2.3 List常用方法及示例

方法描述示例
add(E e)向列表末尾添加元素list.add("Java");
add(int index, E element)在指定位置插入元素list.add(1, "Python");
get(int index)获取指定位置的元素String lang = list.get(0);
set(int index, E element)替换指定位置的元素list.set(1, "C++");
remove(int index)移除指定位置的元素list.remove(0);
remove(Object o)移除第一次出现的指定元素list.remove("Java");
indexOf(Object o)返回元素第一次出现的索引,不存在返回-1int index = list.indexOf("Python");
lastIndexOf(Object o)返回元素最后一次出现的索引,不存在返回-1int lastIndex = list.lastIndexOf("Java");
subList(int from, int to)返回子列表List<String> sub = list.subList(1, 3);
sort(Comparator c)根据Comparator排序列表list.sort(Comparator.naturalOrder());
replaceAll(UnaryOperator u)对每个元素应用操作并替换list.replaceAll(String::toUpperCase);
listIterator()返回列表迭代器,支持双向遍历ListIterator<String> it = list.listIterator();
// 综合示例:管理购物清单
List<String> shoppingList = new ArrayList<>();
shoppingList.add("牛奶");
shoppingList.add("面包");
shoppingList.add("鸡蛋");

// 在指定位置插入
shoppingList.add(1, "水果");

// 替换元素
shoppingList.set(2, "全麦面包");

// 移除元素
shoppingList.remove("鸡蛋");

// 排序
shoppingList.sort(String::compareToIgnoreCase);

// 使用Java 8 forEach遍历
shoppingList.forEach(item -> System.out.println("需要购买: " + item));

// 使用流过滤
List<String> filtered = shoppingList.stream()
                                   .filter(item -> item.length() > 2)
                                   .collect(Collectors.toList());

三、Set接口及其实现类

3.1 HashSet vs LinkedHashSet vs TreeSet

特性HashSetLinkedHashSetTreeSet
底层实现HashMapLinkedHashMapTreeMap
排序无序插入顺序自然顺序或Comparator指定顺序
性能(添加/删除/查找)O(1)O(1)O(log n)
允许null否(如果使用自然排序)
线程安全
适用场景需要快速查找且不关心顺序需要保持插入顺序需要排序
// HashSet示例 - 无序但快速查找
Set<String> hashSet = new HashSet<>();
hashSet.add("Java");
hashSet.add("Python");
hashSet.add("C++");
hashSet.add("Java"); // 重复元素不会被添加

// LinkedHashSet示例 - 保持插入顺序
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Java");
linkedHashSet.add("Python");
linkedHashSet.add("C++");

// TreeSet示例 - 自动排序
Set<String> treeSet = new TreeSet<>();
treeSet.add("Java");
treeSet.add("Python");
treeSet.add("C++");

3.2 Set常用方法及示例

方法描述示例
add(E e)添加元素(如果不存在)set.add("Java");
remove(Object o)移除指定元素set.remove("Java");
contains(Object o)检查是否包含指定元素boolean hasJava = set.contains("Java");
size()返回集合大小int size = set.size();
isEmpty()检查集合是否为空boolean empty = set.isEmpty();
clear()清空集合set.clear();
iterator()返回迭代器Iterator<String> it = set.iterator();
addAll(Collection c)添加集合中所有元素set.addAll(otherSet);
retainAll(Collection c)仅保留指定集合中的元素(交集)set.retainAll(otherSet);
removeAll(Collection c)移除指定集合中的所有元素(差集)set.removeAll(otherSet);
toArray()转换为数组Object[] array = set.toArray();
stream()返回流(Java 8)set.stream().filter(s -> s.startsWith("J")).forEach(System.out::println);
// 综合示例:管理课程集合
Set<String> courseSet = new HashSet<>();
courseSet.add("数学");
courseSet.add("英语");
courseSet.add("物理");

// 检查元素是否存在
if (courseSet.contains("数学")) {
    System.out.println("已选修数学");
}

// 使用迭代器遍历
Iterator<String> iterator = courseSet.iterator();
while (iterator.hasNext()) {
    System.out.println("课程: " + iterator.next());
}

// Java 8 流操作
long count = courseSet.stream()
                     .filter(course -> course.length() > 2)
                     .count();

// 集合运算示例
Set<String> scienceCourses = Set.of("物理", "化学", "生物");

// 并集
Set<String> allCourses = new HashSet<>(courseSet);
allCourses.addAll(scienceCourses);

// 交集
Set<String> commonCourses = new HashSet<>(courseSet);
commonCourses.retainAll(scienceCourses);

// 差集
Set<String> diffCourses = new HashSet<>(courseSet);
diffCourses.removeAll(scienceCourses);

四、Map接口及其实现类

4.1 HashMap vs LinkedHashMap vs TreeMap

特性HashMapLinkedHashMapTreeMap
底层实现数组+链表/红黑树(JDK8+)HashMap+双向链表红黑树
排序无序插入顺序或访问顺序键的自然顺序或Comparator指定顺序
性能(添加/删除/查找)O(1)O(1)O(log n)
允许null键/值是/是是/是否/是(取决于Comparator)
线程安全
内存消耗较低较高(维护链表)较高(树结构)
// HashMap示例 - 快速键值查找
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Java", 1);
hashMap.put("Python", 2);
hashMap.put("C++", 3);

// LinkedHashMap示例 - 保持插入顺序
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("Java", 1);
linkedHashMap.put("Python", 2);
linkedHashMap.put("C++", 3);

// 按访问顺序排序的LinkedHashMap(最近最少使用)
Map<String, Integer> accessOrderMap = new LinkedHashMap<>(16, 0.75f, true);
accessOrderMap.put("Java", 1);
accessOrderMap.put("Python", 2);
accessOrderMap.put("C++", 3);
accessOrderMap.get("Java"); // 访问后Java变为最后一项

// TreeMap示例 - 按键排序
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Java", 1);
treeMap.put("Python", 2);
treeMap.put("C++", 3);

4.2 Map常用方法及示例

方法描述示例
put(K key, V value)添加键值对map.put("Java", 1);
get(Object key)获取指定键的值Integer value = map.get("Java");
remove(Object key)移除指定键的映射map.remove("Java");
containsKey(Object key)检查是否包含指定键boolean hasJava = map.containsKey("Java");
containsValue(Object value)检查是否包含指定值boolean hasValue1 = map.containsValue(1);
size()返回映射数量int size = map.size();
isEmpty()检查映射是否为空boolean empty = map.isEmpty();
clear()清空映射map.clear();
keySet()返回所有键的Set视图Set<String> keys = map.keySet();
values()返回所有值的Collection视图Collection<Integer> values = map.values();
entrySet()返回所有键值对的Set视图Set<Map.Entry<String, Integer>> entries = map.entrySet();
putAll(Map m)添加所有映射map.putAll(otherMap);
getOrDefault(K key, V defaultValue)获取值或默认值(Java 8)int val = map.getOrDefault("Ruby", 0);
putIfAbsent(K key, V value)仅当键不存在时添加(Java 8)map.putIfAbsent("Java", 10);
merge(K key, V value, BiFunction)合并操作(Java 8)map.merge("Java", 1, Integer::sum);
compute(K key, BiFunction)计算新值(Java 8)map.compute("Java", (k, v) -> v == null ? 1 : v + 1);
// 综合示例:学生成绩管理
Map<String, Integer> studentScores = new HashMap<>();
studentScores.put("张三", 85);
studentScores.put("李四", 92);
studentScores.put("王五", 78);

// 检查键是否存在
if (studentScores.containsKey("张三")) {
    System.out.println("张三的成绩已记录");
}

// 遍历键值对(Java 8之前)
for (Map.Entry<String, Integer> entry : studentScores.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// Java 8 forEach遍历
studentScores.forEach((name, score) -> 
    System.out.println(name + "的成绩是: " + score)
);

// 使用流处理
double average = studentScores.values().stream()
                             .mapToInt(Integer::intValue)
                             .average()
                             .orElse(0.0);

// 合并操作示例
Map<String, Integer> additionalScores = new HashMap<>();
additionalScores.put("张三", 5);  // 加分
additionalScores.put("赵六", 88); // 新学生

additionalScores.forEach((name, score) -> 
    studentScores.merge(name, score, Integer::sum)
);

// 计算操作示例
studentScores.computeIfAbsent("钱七", k -> 90); // 如果不存在则添加
studentScores.computeIfPresent("王五", (k, v) -> v + 2); // 如果存在则加分

五、Queue和Deque接口

5.1 Queue实现类比较

特性LinkedListPriorityQueueArrayDeque
底层实现双向链表堆(优先队列)循环数组
排序FIFO自然顺序或Comparator指定顺序FIFO或LIFO
性能(添加/删除)O(1)O(log n)插入,O(1)获取O(1)
允许null
线程安全
适用场景通用队列需要优先级处理的元素高效实现栈和队列
// Queue示例 - 先进先出
Queue<String> queue = new LinkedList<>();
queue.offer("第一人"); // 入队
queue.offer("第二人");
queue.offer("第三人");

String first = queue.poll(); // 出队 - "第一人"

// PriorityQueue示例 - 优先级队列
Queue<Integer> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(5);
priorityQueue.offer(1);
priorityQueue.offer(3);

int firstNum = priorityQueue.poll(); // 1 (最小优先)

// 自定义优先级
Queue<String> customPriority = new PriorityQueue<>(
    (a, b) -> b.length() - a.length() // 按长度降序
);
customPriority.offer("short");
customPriority.offer("very long");
customPriority.offer("medium");

String longest = customPriority.poll(); // "very long"

5.2 Deque实现类比较

特性LinkedListArrayDeque
底层实现双向链表循环数组
性能(添加/删除)O(1)O(1)
内存占用较高(节点开销)较低
随机访问O(n)O(1)
适用场景需要同时作为List和Deque使用纯Deque操作,性能要求高
// Deque示例 - 双端队列
Deque<String> deque = new ArrayDeque<>();
deque.offerFirst("第一"); // 头部添加
deque.offerLast("最后");  // 尾部添加
deque.offer("默认尾部");  // 同offerLast

String first = deque.pollFirst(); // 头部移除
String last = deque.pollLast();   // 尾部移除

// 作为栈使用
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); // 压栈
stack.push(2);
stack.push(3);

int top = stack.pop(); // 弹栈 - 3

5.3 Queue/Deque常用方法

方法Queue描述Deque描述(额外方法)
add(e)/offer(e)添加元素到队尾addLast(e)/offerLast(e)
remove()/poll()移除并返回队头元素removeFirst()/pollFirst()
element()/peek()获取但不移除队头元素getFirst()/peekFirst()
--addFirst(e)/offerFirst(e)
--removeLast()/pollLast()
--getLast()/peekLast()
push(e)-压栈(同addFirst)
pop()-弹栈(同removeFirst)
// 综合示例:银行排队系统
Queue<String> bankQueue = new LinkedList<>();
bankQueue.offer("客户A");
bankQueue.offer("客户B");
bankQueue.offer("VIP客户");

// 处理队列
while (!bankQueue.isEmpty()) {
    String customer = bankQueue.poll();
    System.out.println("正在处理: " + customer);
}

// 使用Deque实现撤销功能
Deque<String> actionHistory = new ArrayDeque<>();
actionHistory.push("添加文本");
actionHistory.push("格式化文档");
actionHistory.push("插入图片");

// 撤销操作
String lastAction = actionHistory.pop();
System.out.println("撤销: " + lastAction);

// 查看但不撤销
String nextAction = actionHistory.peek();
System.out.println("下一个可撤销操作: " + nextAction);

六、Java 8新特性与集合

6.1 Lambda表达式与集合

Java 8引入的Lambda表达式极大简化了集合操作:

List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript");

// 传统匿名类方式
Collections.sort(languages, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
});

// Lambda表达式方式
Collections.sort(languages, (a, b) -> a.length() - b.length());

// 方法引用方式
languages.sort(Comparator.comparingInt(String::length));

// 遍历集合
languages.forEach(System.out::println);

6.2 Stream API

Stream API提供了一种高效处理集合数据的函数式编程方式:

List<Employee> employees = Arrays.asList(
    new Employee("张三", "研发部", 8000),
    new Employee("李四", "市场部", 6000),
    new Employee("王五", "研发部", 9000),
    new Employee("赵六", "销售部", 7000)
);

// 过滤与收集
List<Employee> devTeam = employees.stream()
                                 .filter(e -> "研发部".equals(e.getDepartment()))
                                 .collect(Collectors.toList());

// 分组
Map<String, List<Employee>> byDept = employees.stream()
                                            .collect(Collectors.groupingBy(Employee::getDepartment));

// 计算平均工资
double avgSalary = employees.stream()
                          .mapToInt(Employee::getSalary)
                          .average()
                          .orElse(0);

// 排序与限制
List<Employee> topEarners = employees.stream()
                                   .sorted(Comparator.comparingInt(Employee::getSalary).reversed())
                                   .limit(2)
                                   .collect(Collectors.toList());

6.3 新的Map方法

Java 8为Map接口添加了许多实用方法:

Map<String, Integer> wordCounts = new HashMap<>();
wordCounts.put("Java", 1);
wordCounts.put("Python", 3);

// 如果不存在则计算
wordCounts.computeIfAbsent("C++", k -> 0);

// 如果存在则更新
wordCounts.computeIfPresent("Java", (k, v) -> v + 1);

// 合并值
wordCounts.merge("Python", 1, Integer::sum);

// 遍历
wordCounts.forEach((word, count) -> 
    System.out.println(word + ": " + count)
);

// 获取或默认值
int rubyCount = wordCounts.getOrDefault("Ruby", 0);

6.4 Collectors工具类

Collectors提供了丰富的收集器实现:

List<Employee> employees = // ... 同上

// 转换为Map
Map<String, Integer> nameToSalary = employees.stream()
                                           .collect(Collectors.toMap(
                                               Employee::getName,
                                               Employee::getSalary));

// 分组并计算统计量
Map<String, Double> avgSalaryByDept = employees.stream()
                                             .collect(Collectors.groupingBy(
                                                 Employee::getDepartment,
                                                 Collectors.averagingInt(Employee::getSalary)));

// 分区(按条件分为两部分)
Map<Boolean, List<Employee>> partitioned = employees.stream()
                                                  .collect(Collectors.partitioningBy(
                                                      e -> e.getSalary() > 7000));

// 连接字符串
String allNames = employees.stream()
                         .map(Employee::getName)
                         .collect(Collectors.joining(", "));

// 汇总统计
IntSummaryStatistics stats = employees.stream()
                                    .collect(Collectors.summarizingInt(Employee::getSalary));
System.out.println("平均工资: " + stats.getAverage());
System.out.println("最高工资: " + stats.getMax());

七、集合的线程安全与并发

7.1 传统线程安全集合

描述替代方案(Java 5+)
Vector线程安全的List实现Collections.synchronizedList
Hashtable线程安全的Map实现Collections.synchronizedMap
Stack线程安全的栈实现ArrayDeque
// 同步包装示例
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());

// 使用同步集合
synchronized(syncList) {
    syncList.add("Java");
}

// 遍历时需要同步
synchronized(syncMap) {
    for (Map.Entry<String, Integer> entry : syncMap.entrySet()) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
}

7.2 java.util.concurrent包中的集合

Java 5+引入了更高效的并发集合:

描述特点
ConcurrentHashMap高并发Map实现分段锁,高并发下性能好
CopyOnWriteArrayList写时复制List读多写少场景性能好
ConcurrentLinkedQueue无界线程安全队列非阻塞算法
BlockingQueue阻塞队列接口支持生产者-消费者模式
ConcurrentSkipListMap并发版TreeMap跳表实现,有序
ConcurrentSkipListSet并发版TreeSet跳表实现,有序
// ConcurrentHashMap示例
ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("Java", 1);
concurrentMap.putIfAbsent("Python", 2);

// 原子操作
concurrentMap.compute("Java", (k, v) -> v == null ? 1 : v + 1);

// 遍历不需要同步
concurrentMap.forEach((k, v) -> System.out.println(k + ": " + v));

// CopyOnWriteArrayList示例 - 适合监听器列表等读多写少场景
CopyOnWriteArrayList<String> listeners = new CopyOnWriteArrayList<>();
listeners.add("Listener1");
listeners.add("Listener2");

// 遍历时安全,但可能看到旧数据
listeners.forEach(listener -> System.out.println("通知: " + listener));

// BlockingQueue示例 - 生产者消费者模式
BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);

// 生产者线程
new Thread(() -> {
    try {
        queue.put("任务1");
        queue.put("任务2");
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

// 消费者线程
new Thread(() -> {
    try {
        String task = queue.take();
        System.out.println("处理: " + task);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

7.3 并发集合性能比较

操作HashMapConcurrentHashMapHashtableCollections.synchronizedMap
读(高并发)不安全非常好
写(高并发)不安全非常好
单线程读最好稍慢
单线程写最好稍慢
迭代时修改抛异常安全但不一致抛异常抛异常

选择建议

  • 单线程环境:使用普通集合
  • 多线程读多写少:CopyOnWriteArrayList/CopyOnWriteArraySet
  • 多线程读写频繁:ConcurrentHashMap/ConcurrentSkipListMap
  • 需要阻塞操作:BlockingQueue实现

八、集合的最佳实践与性能优化

8.1 集合选择指南

选择List实现

  • 需要快速随机访问:ArrayList
  • 频繁在任意位置插入删除:LinkedList
  • 多线程环境:CopyOnWriteArrayList(读多写少)或同步包装

选择Set实现

  • 一般用途:HashSet
  • 需要保持插入顺序:LinkedHashSet
  • 需要排序:TreeSet
  • 高并发:ConcurrentSkipListSetCopyOnWriteArraySet

选择Map实现

  • 一般用途:HashMap
  • 需要保持插入顺序:LinkedHashMap
  • 需要排序:TreeMap
  • 高并发:ConcurrentHashMapConcurrentSkipListMap

选择Queue实现

  • 一般队列:LinkedListArrayDeque
  • 优先级队列:PriorityQueue
  • 线程安全队列:ConcurrentLinkedQueue
  • 阻塞队列:ArrayBlockingQueue/LinkedBlockingQueue

8.2 性能优化技巧

  1. 初始化合适容量

    // 避免频繁扩容
    List<String> list = new ArrayList<>(1000);
    Map<String, Integer> map = new HashMap<>(1024, 0.75f);
    
  2. 使用批量操作

    // 避免多次调用add
    List<String> targetList = new ArrayList<>();
    targetList.addAll(sourceList);
    
    // 使用addAll或构造方法
    Set<String> set = new HashSet<>(anotherCollection);
    
  3. 避免不必要的装箱

    // 使用原始类型专用集合
    IntList intList = new IntArrayList(); // (第三方库如Eclipse Collections)
    
  4. 选择合适的数据结构

    // 频繁检查存在性使用Set而不是List
    Set<String> uniqueNames = new HashSet<>(nameList);
    
  5. 利用视图和子集合

    // 不复制数据的情况下操作部分集合
    List<String> subList = largeList.subList(100, 200);
    subList.clear(); // 清除原集合的部分元素
    
  6. 并行流谨慎使用

    // 只有大数据量且无状态操作时才使用并行流
    List<String> result = largeList.parallelStream()
                                  .filter(s -> s.length() > 5)
                                  .collect(Collectors.toList());
    

8.3 常见陷阱与避免方法

  1. 并发修改异常

    List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
    
    // 错误方式 - 会抛出ConcurrentModificationException
    for (String s : list) {
        if ("b".equals(s)) {
            list.remove(s);
        }
    }
    
    // 正确方式1 - 使用迭代器
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        if ("b".equals(it.next())) {
            it.remove();
        }
    }
    
    // 正确方式2 - Java 8 removeIf
    list.removeIf(s -> "b".equals(s));
    
  2. 可变对象作为Map键

    class Employee {
        String name;
        // equals和hashCode基于name
    }
    
    Employee emp = new Employee("张三");
    Map<Employee, String> map = new HashMap<>();
    map.put(emp, "开发");
    
    emp.name = "李四"; // 修改键对象
    System.out.println(map.get(emp)); // 可能返回null
    
  3. 未实现equals/hashCode

    class BadKey {
        int id;
        // 没有重写equals和hashCode
    }
    
    Map<BadKey, String> map = new HashMap<>();
    BadKey key1 = new BadKey();
    key1.id = 1;
    map.put(key1, "值1");
    
    BadKey key2 = new BadKey();
    key2.id = 1;
    System.out.println(map.get(key2)); // 返回null
    
  4. 原始类型集合

    // 自动装箱性能开销
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 1000000; i++) {
        list.add(i); // 发生自动装箱
    }
    
    // 考虑使用第三方原始类型集合
    IntList intList = new IntArrayList(); // Eclipse Collections
    
  5. 集合与数组转换

    List<String> list = Arrays.asList("a", "b", "c");
    
    // 错误方式 - 返回的数组是固定大小的
    String[] array = list.toArray(new String[0]);
    array[0] = "d"; // 修改会影响原List
    
    // 正确方式 - 创建新数组
    String[] newArray = new String[list.size()];
    list.toArray(newArray);
    

九、实战案例:电商系统集合应用

9.1 商品库存管理

// 商品类
class Product {
    private String id;
    private String name;
    private double price;
    private int stock;
    
    // 构造方法、getter/setter省略
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Product product = (Product) o;
        return id.equals(product.id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

// 库存管理
public class InventoryManager {
    private Map<String, Product> productMap = new HashMap<>();
    private Set<Product> lowStockProducts = new TreeSet<>(
        Comparator.comparingInt(Product::getStock)
    );
    
    // 添加商品
    public void addProduct(Product product) {
        productMap.put(product.getId(), product);
        checkLowStock(product);
    }
    
    // 更新库存
    public void updateStock(String productId, int quantity) {
        Product product = productMap.get(productId);
        if (product != null) {
            lowStockProducts.remove(product); // 先移除
            product.setStock(product.getStock() + quantity);
            checkLowStock(product); // 重新检查
        }
    }
    
    // 检查低库存
    private void checkLowStock(Product product) {
        if (product.getStock() < 10) {
            lowStockProducts.add(product);
        }
    }
    
    // 获取低库存商品
    public List<Product> getLowStockProducts() {
        return new ArrayList<>(lowStockProducts);
    }
    
    // 根据价格范围筛选商品
    public List<Product> getProductsInPriceRange(double min, double max) {
        return productMap.values().stream()
                        .filter(p -> p.getPrice() >= min && p.getPrice() <= max)
                        .sorted(Comparator.comparingDouble(Product::getPrice))
                        .collect(Collectors.toList());
    }
}

9.2 订单处理系统

class Order {
    private String orderId;
    private String customerId;
    private LocalDateTime orderDate;
    private List<OrderItem> items;
    private OrderStatus status;
    
    // 构造方法、getter/setter省略
    
    public double getTotalAmount() {
        return items.stream()
                   .mapToDouble(item -> item.getPrice() * item.getQuantity())
                   .sum();
    }
}

enum OrderStatus { PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED }

class OrderItem {
    private String productId;
    private String productName;
    private double price;
    private int quantity;
    
    // 构造方法、getter/setter省略
}

public class OrderProcessor {
    private Queue<Order> pendingOrders = new ConcurrentLinkedQueue<>();
    private Map<String, Order> orderHistory = new ConcurrentHashMap<>();
    private Map<String, List<Order>> customerOrders = new ConcurrentHashMap<>();
    
    // 提交订单
    public void submitOrder(Order order) {
        order.setStatus(OrderStatus.PENDING);
        pendingOrders.offer(order);
        orderHistory.put(order.getOrderId(), order);
        customerOrders.computeIfAbsent(order.getCustomerId(), k -> new ArrayList<>())
                     .add(order);
    }
    
    // 处理订单
    public void processOrders() {
        while (!pendingOrders.isEmpty()) {
            Order order = pendingOrders.poll();
            if (order != null) {
                processOrder(order);
            }
        }
    }
    
    private void processOrder(Order order) {
        order.setStatus(OrderStatus.PROCESSING);
        // 模拟处理逻辑
        try {
            Thread.sleep(100); // 模拟处理时间
            order.setStatus(OrderStatus.SHIPPED);
        } catch (InterruptedException e) {
            order.setStatus(OrderStatus.CANCELLED);
            Thread.currentThread().interrupt();
        }
    }
    
    // 获取客户订单历史
    public List<Order> getCustomerOrders(String customerId) {
        return Collections.unmodifiableList(
            customerOrders.getOrDefault(customerId, Collections.emptyList())
        );
    }
    
    // 统计销售数据
    public Map<String, Double> getSalesByProduct() {
        return orderHistory.values().stream()
                         .flatMap(order -> order.getItems().stream())
                         .collect(Collectors.groupingBy(
                             OrderItem::getProductName,
                             Collectors.summingDouble(item -> item.getPrice() * item.getQuantity())
                         ));
    }
}

9.3 用户购物车实现

public class ShoppingCart {
    private Map<String, CartItem> items = new LinkedHashMap<>(); // 保持添加顺序
    private List<CartObserver> observers = new CopyOnWriteArrayList<>();
    
    // 添加商品
    public void addItem(Product product, int quantity) {
        items.compute(product.getId(), (id, existingItem) -> {
            if (existingItem == null) {
                return new CartItem(product, quantity);
            }
            existingItem.increaseQuantity(quantity);
            return existingItem;
        });
        notifyObservers();
    }
    
    // 移除商品
    public void removeItem(String productId) {
        CartItem removed = items.remove(productId);
        if (removed != null) {
            notifyObservers();
        }
    }
    
    // 更新数量
    public void updateQuantity(String productId, int newQuantity) {
        if (newQuantity <= 0) {
            removeItem(productId);
            return;
        }
        
        CartItem item = items.get(productId);
        if (item != null) {
            item.setQuantity(newQuantity);
            notifyObservers();
        }
    }
    
    // 计算总价
    public double getTotalPrice() {
        return items.values().stream()
                   .mapToDouble(CartItem::getTotalPrice)
                   .sum();
    }
    
    // 获取所有商品
    public List<CartItem> getAllItems() {
        return new ArrayList<>(items.values());
    }
    
    // 清空购物车
    public void clear() {
        items.clear();
        notifyObservers();
    }
    
    // 观察者模式
    public void addObserver(CartObserver observer) {
        observers.add(observer);
    }
    
    public void removeObserver(CartObserver observer) {
        observers.remove(observer);
    }
    
    private void notifyObservers() {
        observers.forEach(observer -> observer.cartUpdated(this));
    }
}

class CartItem {
    private Product product;
    private int quantity;
    
    // 构造方法、getter/setter省略
    
    public double getTotalPrice() {
        return product.getPrice() * quantity;
    }
    
    public void increaseQuantity(int amount) {
        quantity += amount;
    }
}

interface CartObserver {
    void cartUpdated(ShoppingCart cart);
}

十、总结与扩展

10.1 集合框架核心要点总结

  1. List:有序可重复集合,关注索引和顺序

    • ArrayList:随机访问快,插入删除慢
    • LinkedList:插入删除快,随机访问慢
    • Vector:线程安全但性能低
  2. Set:无序不重复集合,关注唯一性

    • HashSet:快速查找,无序
    • LinkedHashSet:保持插入顺序
    • TreeSet:自动排序
  3. Map:键值对映射

    • HashMap:通用键值存储
    • LinkedHashMap:保持插入顺序
    • TreeMap:按键排序
    • ConcurrentHashMap:高并发场景
  4. Queue/Deque:队列和双端队列

    • LinkedList:通用实现
    • ArrayDeque:高效数组实现
    • PriorityQueue:优先级队列
  5. Java 8增强

    • Lambda表达式简化集合操作
    • Stream API提供函数式数据处理
    • 新增Map方法(compute, merge等)

10.2 第三方集合库

  1. Guava (Google Core Libraries for Java)

    • 不可变集合:ImmutableList, ImmutableSet, ImmutableMap
    • 多值Map:Multimap
    • 双向Map:BiMap
    • 表格结构:Table
  2. Eclipse Collections

    • 原始类型集合:IntList, LongSet
    • 丰富的容器类型和算法
  3. Apache Commons Collections

    • 扩展的集合接口和实现
    • 各种实用工具类

10.3 未来发展趋势

  1. Valhalla项目

    • 值类型和专用泛型
    • 可能减少集合的装箱开销
  2. 更丰富的流操作

    • Java 9+增加了更多Stream操作
    • 响应式流集成
  3. 记录类(Record)与集合

    • Java 16引入的记录类简化了值对象
    • 与集合框架更好集成
// Java 16记录类示例
record ProductRecord(String id, String name, double price) {}

List<ProductRecord> products = List.of(
    new ProductRecord("p1", "Laptop", 999.99),
    new ProductRecord("p2", "Phone", 699.99)
);

// 自动实现equals/hashCode/toString等
Map<String, ProductRecord> productMap = products.stream()
    .collect(Collectors.toMap(ProductRecord::id, Function.identity()));

通过这篇全面的指南,你应该已经掌握了Java集合框架从基础到高级的所有核心概念。记住,选择正确的集合类型和实现类对于编写高效、可维护的代码至关重要。随着Java语言的演进,集合框架也在不断发展,保持学习是成为优秀Java程序员的关键。

Java 集合框架就是代码界的 “收纳大冤种”!List 是排队狂魔,Map 玩记忆游戏,敢用错?程序当场表演 “数据离家出走”!

“本文耗费我3小时+2包薯片,点赞不过分吧?”

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clf丶忆笙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值