第48章

Java集合框架概述

掌握Collection、List、Set、Map接口体系与集合框架设计原理

学习目标

Java集合框架概述

Java集合框架(Java Collections Framework,JCF)是Java平台中用于存储和操作对象集合的统一架构。它提供了一套设计良好的接口和实现,用于表示和操作集合,使程序员能够高效地处理数据。

集合框架的核心优势

  • 统一的架构:提供一致的API来操作不同类型的集合
  • 高性能:针对不同场景优化的数据结构实现
  • 互操作性:不同集合类型之间可以相互转换
  • 可扩展性:可以轻松创建自定义集合实现

集合框架层次结构

Java集合框架继承体系图

Iterable<E>
    ↓
Collection<E>
    ├── List<E>
    │   ├── ArrayList<E>
    │   ├── LinkedList<E>
    │   ├── Vector<E>
    │   └── Stack<E>
    ├── Set<E>
    │   ├── HashSet<E>
    │   ├── LinkedHashSet<E>
    │   └── SortedSet<E>
    │       └── TreeSet<E>
    └── Queue<E>
        ├── PriorityQueue<E>
        └── Deque<E>
            └── ArrayDeque<E>

Map<K,V> (独立体系)
    ├── HashMap<K,V>
    ├── LinkedHashMap<K,V>
    ├── Hashtable<K,V>
    └── SortedMap<K,V>
        └── TreeMap<K,V>

重要说明

Map接口并不继承Collection接口,它是一个独立的接口体系。Map表示键值对的映射关系,而Collection表示单一元素的集合。

核心接口详解

Collection接口

所有集合类的根接口,定义了集合的基本操作。

  • 添加和删除元素
  • 查询集合大小和状态
  • 迭代器支持
  • 批量操作方法
  • 转换为数组
基本方法:
boolean add(E e)
boolean remove(Object o)
int size()
boolean isEmpty()
Iterator<E> iterator()

List接口

有序集合,允许重复元素,支持索引访问。

  • 按索引访问元素
  • 允许重复元素
  • 保持插入顺序
  • 支持位置插入和删除
  • 提供ListIterator
特有方法:
E get(int index)
E set(int index, E element)
void add(int index, E element)
E remove(int index)
int indexOf(Object o)

Set接口

不允许重复元素的集合,基于数学集合概念。

  • 不允许重复元素
  • 最多包含一个null元素
  • 基于equals()方法判断重复
  • 支持集合运算
  • 无索引访问
继承Collection的方法:
// Set没有定义额外方法
// 但对add()等方法有特殊约束
boolean add(E e) // 重复元素返回false

Queue接口

队列接口,通常按FIFO(先进先出)方式排序元素。

  • FIFO排序(通常)
  • 队列头部操作
  • 提供两套方法(抛异常/返回特殊值)
  • 支持优先级队列
  • 双端队列扩展
队列操作:
boolean offer(E e) // 入队
E poll()           // 出队
E peek()           // 查看队头
boolean add(E e)   // 入队(抛异常)
E remove()         // 出队(抛异常)

Map接口

键值对映射,每个键最多映射一个值。

  • 键值对存储
  • 键不能重复
  • 值可以重复
  • 支持null键和值(取决于实现)
  • 提供三种视图
基本操作:
V put(K key, V value)
V get(Object key)
V remove(Object key)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet()

SortedSet接口

有序Set,元素按自然顺序或Comparator排序。

  • 元素自动排序
  • 支持范围查询
  • 提供首尾元素访问
  • 子集视图
  • Comparator支持
排序相关方法:
E first()
E last()
SortedSet<E> headSet(E toElement)
SortedSet<E> tailSet(E fromElement)
Comparator<? super E> comparator()

主要实现类比较

List实现类比较

实现类 底层结构 访问性能 插入/删除性能 线程安全 适用场景
ArrayList 动态数组 O(1) O(n) 频繁随机访问
LinkedList 双向链表 O(n) O(1) 频繁插入删除
Vector 动态数组 O(1) O(n) 线程安全需求

Set实现类比较

实现类 底层结构 性能 排序 null支持 适用场景
HashSet 哈希表 O(1) 无序 支持 快速查找
LinkedHashSet 哈希表+链表 O(1) 插入顺序 支持 保持插入顺序
TreeSet 红黑树 O(log n) 自然排序 不支持 需要排序

Map实现类比较

实现类 底层结构 性能 排序 null支持 线程安全
HashMap 哈希表 O(1) 无序 键值都支持
LinkedHashMap 哈希表+链表 O(1) 插入/访问顺序 键值都支持
TreeMap 红黑树 O(log n) 键自然排序 值支持
Hashtable 哈希表 O(1) 无序 都不支持

集合框架使用示例

基本集合操作示例:
import java.util.*;

public class CollectionsDemo {
    public static void main(String[] args) {
        // List示例 - 有序,允许重复
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Apple"); // 允许重复
        System.out.println("List: " + list); // [Apple, Banana, Apple]
        
        // Set示例 - 无重复元素
        Set<String> set = new HashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Apple"); // 重复元素被忽略
        System.out.println("Set: " + set); // [Apple, Banana]
        
        // Map示例 - 键值对
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 5);
        map.put("Banana", 3);
        map.put("Orange", 8);
        System.out.println("Map: " + map); // {Apple=5, Banana=3, Orange=8}
        
        // Queue示例 - 队列操作
        Queue<String> queue = new LinkedList<>();
        queue.offer("First");
        queue.offer("Second");
        queue.offer("Third");
        System.out.println("Queue poll: " + queue.poll()); // First
        System.out.println("Queue: " + queue); // [Second, Third]
    }
}
💻 查看完整代码 - 在线IDE体验

选择集合的原则

如何选择合适的集合类型

选择建议

  • 需要索引访问 → 选择List
  • 不允许重复 → 选择Set
  • 键值对存储 → 选择Map
  • FIFO操作 → 选择Queue
  • 频繁随机访问 → ArrayList
  • 频繁插入删除 → LinkedList
  • 需要排序 → TreeSet/TreeMap
  • 线程安全 → Vector/Hashtable

避免的误区

  • 不考虑性能特点盲目选择
  • 在单线程环境使用同步集合
  • 频繁插入删除时使用ArrayList
  • 需要排序时使用HashMap
  • 忽略集合的容量设置
  • 不合理的集合嵌套
  • 忘记重写equals和hashCode
  • 在循环中修改集合结构

性能考虑

性能优化建议

  • 初始容量:为ArrayList、HashMap等设置合适的初始容量
  • 负载因子:HashMap的负载因子影响性能和内存使用
  • 迭代器:使用迭代器而不是索引遍历LinkedList
  • 批量操作:使用addAll()等批量操作方法
  • 并发考虑:多线程环境下选择合适的并发集合
性能优化示例:
// 设置初始容量避免频繁扩容
List<String> list = new ArrayList<>(1000);
Map<String, String> map = new HashMap<>(16, 0.75f);

// 使用批量操作
List<String> source = Arrays.asList("a", "b", "c");
List<String> target = new ArrayList<>();
target.addAll(source); // 比逐个add效率高

// 正确的遍历方式
for (String item : list) {
    // 使用增强for循环
}

// 或使用迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String item = it.next();
    // 处理元素
}

章节总结