Java集合框架详解


Java集合框架(Java Collections Framework)是Java中用于存储和操作数据集合的一组接口和类,提供了高效的数据结构和算法实现。

一、集合框架概述

1. 核心接口层次结构

Iterable (接口)
└── Collection (接口)
    ├── List (接口)
    ├── Set (接口)
    │   └── SortedSet (接口)
    └── Queue (接口)
        └── Deque (接口)

Map (接口)
└── SortedMap (接口)

2. 主要实现类对比

接口有序允许重复允许null线程安全主要实现类
ListArrayList, LinkedList, Vector
Set否*是**HashSet, LinkedHashSet, TreeSet
Queue是***LinkedList, PriorityQueue
Map否*key唯一key/valueHashMap, LinkedHashMap, TreeMap

TreeSet/TreeMap是有序的;TreeSet不允许null元素;某些Queue实现不允许null

二、List接口及实现类

1. ArrayList

特点

  • 基于动态数组实现
  • 随机访问快(O(1))
  • 插入删除慢(O(n))
  • 初始容量10,扩容1.5倍

常用方法

List<String> list = new ArrayList<>();
list.add("A");          // 添加元素
list.add(1, "B");       // 指定位置插入
list.get(0);            // 获取元素
list.remove(0);         // 删除元素
list.set(0, "C");       // 修改元素
list.indexOf("B");      // 查找索引
list.subList(1, 3);     // 获取子列表

2. LinkedList

特点

  • 基于双向链表实现
  • 插入删除快(O(1))
  • 随机访问慢(O(n))
  • 实现了List和Deque接口

特有方法

LinkedList<String> list = new LinkedList<>();
list.addFirst("A");     // 头部添加
list.addLast("B");      // 尾部添加
list.getFirst();        // 获取头部
list.getLast();         // 获取尾部
list.removeFirst();     // 移除头部
list.removeLast();      // 移除尾部

3. Vector vs ArrayList

特性VectorArrayList
同步是(线程安全)
扩容默认2倍1.5倍
迭代器Enumeration和IteratorIterator
性能较低较高
遗留类

三、Set接口及实现类

1. HashSet

特点

  • 基于HashMap实现
  • 无序集合
  • 允许null元素
  • 添加/删除/查找O(1)

示例

Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.contains("A");  // true
set.remove("B");

2. LinkedHashSet

特点

  • 继承HashSet
  • 维护插入顺序
  • 性能略低于HashSet

3. TreeSet

特点

  • 基于TreeMap实现
  • 元素按自然顺序或Comparator排序
  • 基本操作O(log n)

示例

Set<String> set = new TreeSet<>(Comparator.reverseOrder());
set.add("C");
set.add("A");
set.add("B");
// 结果为[C, B, A]

四、Map接口及实现类

1. HashMap

特点

  • 数组+链表+红黑树(JDK8+)
  • 初始容量16,负载因子0.75
  • 允许null键和null值
  • 非线程安全

常用方法

Map<String, Integer> map = new HashMap<>();
map.put("A", 1);        // 添加键值对
map.get("A");           // 获取值
map.containsKey("A");   // 检查键
map.remove("A");        // 删除
map.keySet();           // 获取所有键
map.values();           // 获取所有值
map.forEach((k, v) -> System.out.println(k + ": " + v)); // 遍历

2. LinkedHashMap

特点

  • 继承HashMap
  • 维护插入顺序或访问顺序
  • 可用于实现LRU缓存

示例

// 按访问顺序排序(最近最少使用在前)
Map<String, Integer> lruMap = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {
        return size() > 3;  // 最大保留3个元素
    }
};

3. TreeMap

特点

  • 基于红黑树实现
  • 按键的自然顺序或Comparator排序
  • 基本操作O(log n)

示例

Map<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
map.put("B", 2);
map.put("a", 1);  // 不区分大小写
// 顺序为{a=1, B=2}

五、Queue/Deque接口及实现类

1. PriorityQueue

特点

  • 基于优先级堆(通常是最小堆)
  • 不允许null元素
  • 元素必须实现Comparable或提供Comparator

示例

Queue<Integer> pq = new PriorityQueue<>();
pq.offer(3);  // 添加元素
pq.offer(1);
pq.offer(2);
pq.poll();    // 移除并返回头部(1)

2. ArrayDeque

特点

  • 基于循环数组实现
  • 比LinkedList更高效
  • 可用作栈或队列

示例

Deque<String> deque = new ArrayDeque<>();
// 作为栈使用
deque.push("A");  // 入栈
deque.push("B");
deque.pop();      // 出栈(B)
// 作为队列使用
deque.offer("C"); // 入队
deque.poll();     // 出队(A)

六、工具类Collections

常用方法

List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2));

Collections.sort(list);                  // 排序[1, 2, 3]
Collections.reverse(list);               // 反转[3, 2, 1]
Collections.shuffle(list);               // 随机打乱
Collections.binarySearch(list, 2);       // 二分查找
Collections.max(list);                   // 最大值
Collections.min(list);                   // 最小值
Collections.replaceAll(list, 2, 4);      // 替换所有2为4

// 创建不可变集合
List<Integer> unmodifiable = Collections.unmodifiableList(list);

// 创建同步集合
List<Integer> synchronizedList = Collections.synchronizedList(list);

七、Java 8+新特性

1. Stream API操作集合

List<String> list = Arrays.asList("A", "B", "C");

// 过滤
list.stream().filter(s -> s.startsWith("A")).count();

// 映射
list.stream().map(String::toLowerCase).collect(Collectors.toList());

// 排序
list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

// 分组
Map<Integer, List<String>> groupByLength = 
    list.stream().collect(Collectors.groupingBy(String::length));

// 统计
IntSummaryStatistics stats = 
    list.stream().collect(Collectors.summarizingInt(String::length));

2. Map新增方法

Map<String, Integer> map = new HashMap<>();

// 键不存在时计算值
map.computeIfAbsent("A", k -> k.length());  // A=1

// 键存在时重新计算值
map.computeIfPresent("A", (k, v) -> v + 1); // A=2

// 合并值
map.merge("A", 1, (oldVal, newVal) -> oldVal + newVal); // A=3

// 遍历
map.forEach((k, v) -> System.out.println(k + ":" + v));

八、集合使用最佳实践

  1. 选择合适的集合类型
  • 需要快速随机访问 → ArrayList
  • 频繁插入删除 → LinkedList
  • 去重 → HashSet
  • 键值对 → HashMap
  • 排序 → TreeSet/TreeMap
  1. 预估容量:构造集合时指定初始容量避免频繁扩容
  2. 遍历集合
  • 使用Iterator或增强for循环修改集合会抛出ConcurrentModificationException
  • 需要修改时使用Iterator的remove()方法
  1. 线程安全
  • 使用Collections.synchronizedXXX()包装
  • 或使用java.util.concurrent包下的并发集合
  1. 性能考虑
  • ArrayList vs LinkedList
  • HashMap vs TreeMap
  • HashSet vs TreeSet
  1. 不可变集合
  • 使用Collections.unmodifiableXXX()
  • Java 9+的List.of(), Set.of(), Map.of()

掌握Java集合框架对于编写高效、可维护的Java程序至关重要。理解各种集合的实现原理和适用场景,可以帮助你在实际开发中做出最佳选择。

,

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注