8-Java集合

一、集合框架概述

Java集合框架(Java Collections Framework, JCF)是Java中用于存储、操作和管理数据集合的标准化架构。它通过统一的接口和实现类,提供高效的数据结构和算法支持。

核心组成:

  1. 接口:定义集合的抽象行为(如Collection, List, Set, Map)。
  2. 实现类:接口的具体实现(如ArrayList, HashSet, HashMap)。
  3. 算法:工具类Collections提供的排序、查找等通用操作。
  4. 迭代器IteratorListIterator,用于遍历集合元素。

二、核心接口与实现类

1. Collection接口

  • 定义:所有集合类的根接口(除了Map)。
  • 核心子接口
    • List:有序集合,允许重复元素。
    • Set:无序集合,不允许重复元素。
    • Queue:队列,支持先进先出(FIFO)或优先级操作。
boolean add(E e);    // 添加元素 
 boolean remove(Object o); // 删除元素 
 int size();        // 返回元素数量 
 Iterator<E> iterator();  // 获取迭代器 

2. List接口

特点:有序、可重复、支持索引访问。

实现类数据结构线程安全适用场景
ArrayList动态数组频繁查询,较少插入删除
LinkedList双向链表频繁插入删除,较少查询
Vector动态数组遗留类,已被ArrayList替代
CopyOnWriteArrayList写时复制数组读多写少的高并发场景
List<String> arrayList = new ArrayList<>(); 
 arrayList.add("Java"); 
 arrayList.get(0); // 通过索引访问 

 List<String> linkedList = new LinkedList<>(); 
 linkedList.addFirst("First"); // 链表头插入 

3. Set接口

特点:无序、元素唯一。

实现类数据结构排序线程安全
HashSet哈希表
LinkedHashSet哈希表+链表插入顺序
TreeSet红黑树自然排序
CopyOnWriteArraySet写时复制数组
Set<Integer> hashSet = new HashSet<>(); 
 hashSet.add(1); 
 hashSet.add(1); // 重复元素被忽略 

 Set<String> treeSet = new TreeSet<>(); 
 treeSet.add("Banana"); // 自动按字典序排序 

4. Queue接口

特点:队列操作,支持FIFO或优先级。

实现类数据结构特性
LinkedList链表可用作普通队列
PriorityQueue堆(数组实现)元素按优先级排序
ArrayDeque动态数组双端队列,高效头尾操作
BlockingQueue多种实现线程安全的阻塞队列
Queue<Integer> queue = new LinkedList<>(); 
 queue.offer(1); // 入队 
 queue.poll();  // 出队 

 Queue<Integer> priorityQueue = new PriorityQueue<>(); 
 priorityQueue.offer(3); 
 priorityQueue.offer(1); // 自动按升序排序

5. Map接口

特点:键值对存储,键唯一。

实现类数据结构线程安全排序特性
HashMap哈希表无序
LinkedHashMap哈希表+链表插入顺序/访问顺序
TreeMap红黑树键自然排序
Hashtable哈希表遗留类
ConcurrentHashMap分段锁哈希表高并发优化
Map<String, Integer> hashMap = new HashMap<>(); 
 hashMap.put("Java", 1); 
 hashMap.get("Java"); // 返回值1 

 Map<String, Integer> treeMap = new TreeMap<>(); 
 treeMap.put("Banana", 2); // 按键字典序排序 

三、集合工具类Collections

提供静态方法操作集合,常见功能包括:

  1. 排序sort(List<T> list)
  2. 查找binarySearch(List<T> list, T key)
  3. 同步包装synchronizedList(List<T> list)
  4. 不可变集合unmodifiableList(List<T> list)
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2)); 
 Collections.sort(list); // [1, 2, 3] 
 List<Integer> syncList = Collections.synchronizedList(list); // 线程安全包装 

四、迭代器与遍历

1.Iterator接口

Iterator<String> it = list.iterator(); 
 while (it.hasNext()) { 
   String element = it.next(); 
   it.remove(); // 安全删除当前元素 
 } 

2.ListIterator接口

  • 支持双向遍历(hasPrevious(), previous())。
  • 允许在遍历时修改列表(add(), set())。

3. 增强for循环

for (String s : list) { 
   System.out.println(s); 
 } 

五、Java 8+ 新特性

1. Lambda表达式与集合操作

list.forEach(element -> System.out.println(element)); 
 list.removeIf(element -> element.length() < 3); 

2. Stream API:

List<String> filtered = list.stream() 
               .filter(s -> s.startsWith("A")) 
               .sorted() 
               .collect(Collectors.toList()); 

3. 新的集合工厂方法(Java 9+):

List<String> immutableList = List.of("A", "B", "C"); // 不可变集合 
 Map<String, Integer> immutableMap = Map.of("Java", 1, "C++", 2); 

六、性能与选择指南

场景推荐实现类原因
频繁查询ArrayList动态数组支持O(1)随机访问
频繁插入删除LinkedList链表操作时间复杂度O(1)
需要唯一元素HashSet哈希表实现O(1)查找
需要排序TreeSet/TreeMap红黑树支持自然排序
高并发读多写少CopyOnWriteArrayList写时复制保证线程安全
高并发读写ConcurrentHashMap分段锁优化并发性能

七、常见问题与解决方案

1. ConcurrentModificationException

  • 原因:遍历集合时直接修改集合结构(如删除元素)。
  • 解决:使用迭代器的remove()方法,或CopyOnWriteArrayList

2. 选择HashMap还是Hashtable

  • HashMap:非线程安全,性能更高。
  • ConcurrentHashMap:替代Hashtable,支持高并发。

3. 集合与数组转换

String[] array = list.toArray(new String[0]); // List转数组 
 List<String> list = Arrays.asList(array);   // 数组转List(固定大小) 

八、集合存储原理

1. ArrayList(动态数组)

  • 数据结构:基于数组实现,支持动态扩容。
  • 存储机制
    • 初始化:默认容量为10,可指定初始容量。
    • 扩容:当元素数量超过当前容量时,容量扩展为原来的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1))。
    • 内存分配:每次扩容时创建新数组并复制旧数据,时间复杂度为O(n)
  • 操作复杂度
    • 访问O(1)(通过索引直接定位)。
    • 插入/删除O(n)(需要移动后续元素)。
ArrayList<Integer> list = new ArrayList<>();
 list.add(1); // 初始容量为10
 for (int i = 0; i < 15; i++) list.add(i); // 触发扩容至15

3.LinkedList(双向链表)

  • 数据结构:每个节点(Node)包含前驱、后继指针和元素值。
  • 存储机制
    • 插入/删除:只需修改相邻节点的指针,时间复杂度O(1)(已知位置时)。
    • 访问:需从头或尾遍历链表,时间复杂度O(n)
  • 内存占用:每个元素需额外存储两个指针,空间复杂度高于ArrayList
private static class Node<E> {
   E item;
   Node<E> next;
   Node<E> prev;
 }

3.HashMap(哈希表+链表/红黑树)

  • 数据结构:数组(桶) + 链表或红黑树(解决哈希冲突)。

  • 存储机制

    • 哈希函数key.hashCode()的高16位异或低16位,均匀分布哈希值。
    • 桶定位index = (n - 1) & hash,其中n为桶数组长度(2的幂)。
    • 冲突解决
  • 链表:当链表长度≥8且桶数量≥64时,链表转为红黑树(时间复杂度从O(n)优化为O(log n))。

  • 红黑树:当红黑树节点≤6时,退化为链表。

  • 扩容:默认负载因子0.75,当元素数超过容量*负载因子时,容量翻倍并重新哈希。

操作复杂度:

  • 插入/查找/删除:平均O(1),最坏O(log n)(红黑树)。
HashMap<String, Integer> map = new HashMap<>();
 map.put("Java", 1); // 哈希值为"Java".hashCode()

4. TreeSet(红黑树)

  • 数据结构:基于TreeMap实现,使用红黑树保持元素有序。
  • 存储机制
    • 排序规则:自然排序(Comparable)或自定义比较器(Comparator)。
    • 插入/删除:通过红黑树自平衡保证操作复杂度为O(log n)
  • 内存占用:每个节点需存储父节点、左右子节点指针及颜色标记。
TreeSet<Integer> treeSet = new TreeSet<>((a, b) -> b - a); // 降序排列
 treeSet.add(3); // 插入时自动调整树结构

九、集合遍历机制

1. 迭代器(Iterator

  • 实现原理
    • ArrayList:通过索引直接访问元素。
    • LinkedList:记录当前遍历的节点指针。
    • HashMap:依次遍历桶数组中的链表或红黑树。
Iterator<String> it = list.iterator();
 while (it.hasNext()) {
   String element = it.next();
   it.remove(); // 安全删除当前元素
 }
  • Fail-Fast机制
    • 遍历时若集合被修改(非通过迭代器自身方法),抛出ConcurrentModificationException
    • 实现方式:检查modCount(修改计数器)是否与预期值一致。

2. 增强for循环

  • 底层实现:编译后转换为迭代器遍历。
// 源码
 for (String s : list) { ... }

 // 编译后等效代码
 Iterator<String> it = list.iterator();
 while (it.hasNext()) {
   String s = it.next();
   ...
 }

3. ListIterator(双向遍历)

  • 特性
    • 支持向前(hasPrevious(), previous())和向后遍历。
    • 允许在遍历时修改列表(add(), set())。
  • 应用场景:需要反向遍历或边遍历边修改。
ListIterator<String> lit = list.listIterator(list.size());
 while (lit.hasPrevious()) {
   String prev = lit.previous();
 }

十、不同集合遍历性能对比

集合类型遍历方式时间复杂度适用场景
ArrayList索引for循环O(n)频繁随机访问
LinkedList迭代器O(n)避免使用索引遍历(O(n^2))
HashSet迭代器O(n)无序遍历
LinkedHashSet迭代器O(n)按插入顺序遍历
TreeSet迭代器O(n)按排序顺序遍历
HashMap迭代器(EntrySet)O(n)遍历键值对

十一、遍历中的常见问题与解决方案

1. ConcurrentModificationException

  • 原因:在遍历过程中直接调用集合的add()remove()方法。
  • 解决:使用迭代器的remove()方法或CopyOnWriteArrayList

2. 遍历删除元素

// 错误方式
 for (String s : list) {
   if (s.equals("Java")) list.remove(s); // 抛出异常
 }

 // 正确方式
 Iterator<String> it = list.iterator();
 while (it.hasNext()) {
   if (it.next().equals("Java")) it.remove();
 }

3. 遍历大型集合优化

  • 使用Stream的并行流加速处理
list.parallelStream().forEach(...);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值