Java集合框架解析

一、集合框架概述

1. 集合框架体系结构

Java集合框架(Java Collections Framework, JCF)位于java.util包中,包含三大核心接口:

  • Collection :单列数据集合的根接口
    • List:有序可重复集合
    • Set:无序不可重复集合
    • Queue:队列集合
  • Map:双列键值对集合
  • Iterator:集合遍历接口

2. 核心接口继承关系

复制代码
Collection
├── List
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector
│       └── Stack
├── Set
│   ├── HashSet
│   │   └── LinkedHashSet
│   └── SortedSet
│       └── TreeSet
└── Queue
    ├── Deque
    │   ├── ArrayDeque
    │   └── LinkedList
    └── PriorityQueue

Map
├── HashMap
│   └── LinkedHashMap
├── Hashtable
└── SortedMap
    └── TreeMap

二、基础集合使用

1. List接口实现

ArrayList
java 复制代码
// 创建ArrayList
List<String> arrayList = new ArrayList<>();

// 添加元素
arrayList.add("Java");
arrayList.add("Python");
arrayList.add(1, "C++"); // 在指定位置插入

// 访问元素
String lang = arrayList.get(0); // "Java"

// 遍历
for (String s : arrayList) {
    System.out.println(s);
}

// 删除元素
arrayList.remove("Python");
arrayList.remove(0);
LinkedList
java 复制代码
// 创建LinkedList
List<String> linkedList = new LinkedList<>();

// 特有方法
LinkedList<String> list = (LinkedList<String>) linkedList;
list.addFirst("First");
list.addLast("Last");
String first = list.getFirst();
String last = list.getLast();

2. Set接口实现

HashSet
java 复制代码
Set<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Apple"); // 重复元素不会被添加

System.out.println(hashSet); // [Apple, Banana]
TreeSet
java 复制代码
Set<Integer> treeSet = new TreeSet<>((a, b) -> b - a); // 自定义排序
treeSet.add(5);
treeSet.add(2);
treeSet.add(8);

System.out.println(treeSet); // [8, 5, 2]

3. Map接口实现

HashMap
java 复制代码
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Alice", 25);
hashMap.put("Bob", 30);
hashMap.put("Charlie", 28);

// 获取值
int age = hashMap.get("Bob");

// 遍历
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
TreeMap
java 复制代码
Map<String, Integer> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
treeMap.put("Banana", 3);
treeMap.put("apple", 5);
treeMap.put("Orange", 2);

System.out.println(treeMap); // {apple=5, Banana=3, Orange=2}

三、集合转换操作

1. 集合间相互转换

List ↔ Set
java 复制代码
// List转Set(去重)
List<String> listWithDuplicates = Arrays.asList("A", "B", "A", "C");
Set<String> set = new HashSet<>(listWithDuplicates); // [A, B, C]

// Set转List
List<String> listFromSet = new ArrayList<>(set);
数组 ↔ List
java 复制代码
// 数组转List
String[] array = {"Java", "Python", "C++"};
List<String> list = Arrays.asList(array); // 固定大小List
List<String> mutableList = new ArrayList<>(Arrays.asList(array));

// List转数组
String[] newArray = list.toArray(new String[0]);
Map ↔ Set
java 复制代码
// Map的key转Set
Set<String> keys = hashMap.keySet();

// Map的entry转Set
Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();

// Set转Map(需要元素包含键值信息)
Set<Pair<String, Integer>> pairSet = new HashSet<>();
// ...添加元素
Map<String, Integer> mapFromSet = pairSet.stream()
    .collect(Collectors.toMap(Pair::getKey, Pair::getValue));

2. 不可变集合

Java 9+创建不可变集合
java 复制代码
List<String> immutableList = List.of("A", "B", "C");
Set<Integer> immutableSet = Set.of(1, 2, 3);
Map<String, Integer> immutableMap = Map.of("A", 1, "B", 2);

// 尝试修改会抛出UnsupportedOperationException
// immutableList.add("D"); // 错误
Collections工具类创建
java 复制代码
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> unmodifiableList = Collections.unmodifiableList(list);

四、集合流式处理(Java 8+)

1. 基本流操作

过滤与映射
java 复制代码
List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript", "Ruby");

// 过滤长度大于3的元素
List<String> filtered = languages.stream()
    .filter(s -> s.length() > 3)
    .collect(Collectors.toList()); // [Java, Python, JavaScript, Ruby]

// 转换为大写
List<String> upperCase = languages.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
聚合操作
java 复制代码
// 统计
long count = languages.stream().count();
Optional<String> max = languages.stream().max(Comparator.naturalOrder());

// 求和
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);

2. 高级流操作

分组与分区
java 复制代码
// 按长度分组
Map<Integer, List<String>> groupByLength = languages.stream()
    .collect(Collectors.groupingBy(String::length));
// {2=[C++], 4=[Java, Ruby], 6=[Python], 10=[JavaScript]}

// 分区(满足条件的和其他的)
Map<Boolean, List<String>> partition = languages.stream()
    .collect(Collectors.partitioningBy(s -> s.startsWith("J")));
// {false=[Python, C++, Ruby], true=[Java, JavaScript]}
并行流
java 复制代码
// 顺序流
long count = languages.stream().filter(s -> s.length() > 3).count();

// 并行流(大数据量性能更好)
long parallelCount = languages.parallelStream().filter(s -> s.length() > 3).count();

五、集合与数组转换

1. 集合转数组

传统方式
java 复制代码
List<String> list = Arrays.asList("A", "B", "C");
String[] array = list.toArray(new String[0]); // 推荐使用空数组
Java 8+ Stream方式
java 复制代码
String[] array = list.stream().toArray(String[]::new);

2. 数组转集合

标准方式
java 复制代码
String[] array = {"A", "B", "C"};

// 固定大小List(不可修改)
List<String> asList = Arrays.asList(array);

// 可变List
List<String> mutableList = new ArrayList<>(Arrays.asList(array));
Java 8+ Stream方式
java 复制代码
List<String> list = Arrays.stream(array).collect(Collectors.toList());

// 去重
Set<String> set = Arrays.stream(array).collect(Collectors.toSet());

六、集合框架底层实现

1. ArrayList实现原理

  • 底层结构 :动态数组Object[] elementData
  • 扩容机制 :
    • 默认初始容量10
    • 扩容时newCapacity = oldCapacity + (oldCapacity >> 1)(约1.5倍)
    • 最大容量Integer.MAX_VALUE - 8
  • 特点 :
    • 随机访问快(O(1))
    • 插入删除慢(平均O(n))
    • 线程不安全

2. LinkedList实现原理

  • 底层结构 :双向链表

    java 复制代码
    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;
        // ...
    }
  • 特点 :

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

3. HashMap实现原理(Java 8+)

  • 底层结构 :数组+链表+红黑树

    • 默认初始容量16,负载因子0.75
    • 链表长度>8且数组长度≥64时,链表转红黑树
    • 树节点数<6时,红黑树转链表
  • 哈希计算 :

    java 复制代码
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
  • 扩容机制 :

    • 容量变为2倍
    • 重新计算节点位置:newTab[e.hash & (newCap - 1)]

4. TreeMap实现原理

  • 底层结构:红黑树(自平衡二叉查找树)
  • 排序规则 :
    • 自然排序(元素实现Comparable)
    • 或通过Comparator自定义排序
  • 特点 :
    • 查找、插入、删除时间复杂度O(log n)
    • 保持元素有序

七、集合框架性能比较

1. List实现比较

操作 ArrayList LinkedList
get(int) O(1) O(n)
add(E) 平均O(1) O(1)
add(int, E) O(n) O(1)
remove(int) O(n) O(1)
内存占用 较小(仅数组) 较大(节点开销)

2. Set实现比较

特性 HashSet LinkedHashSet TreeSet
底层实现 HashMap LinkedHashMap TreeMap
顺序 无序 插入顺序 自然/自定义排序
时间复杂度 O(1) O(1) O(log n)
线程安全 否 否 否

3. Map实现比较

特性 HashMap LinkedHashMap TreeMap Hashtable
底层实现 数组+链表+红黑树 链表+哈希表 红黑树 数组+链表
顺序 无序 插入/访问顺序 键排序 无序
线程安全 否 否 否 是
允许null 是 是 否 否

八、线程安全集合

1. 传统线程安全集合

Vector和Hashtable
java 复制代码
// 线程安全但性能较差
Vector<String> vector = new Vector<>();
Hashtable<String, Integer> hashtable = new Hashtable<>();
Collections.synchronizedXXX
java 复制代码
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());

2. Java 5+并发集合

CopyOnWriteArrayList
java 复制代码
// 写时复制,适合读多写少场景
List<String> cowList = new CopyOnWriteArrayList<>();
ConcurrentHashMap
java 复制代码
// 分段锁实现高并发
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
BlockingQueue
java 复制代码
// 阻塞队列
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("item");  // 阻塞直到空间可用
String item = queue.take();  // 阻塞直到元素可用

九、最佳实践

1. 集合选择策略

  • 需要快速随机访问:ArrayList
  • 频繁插入删除:LinkedList
  • 去重存储:HashSet/LinkedHashSet/TreeSet
  • 键值存储:HashMap/LinkedHashMap/TreeMap
  • 线程安全:ConcurrentHashMap/CopyOnWriteArrayList

2. 性能优化建议

  1. 初始化合适容量:

    java 复制代码
    new ArrayList<>(100);  // 避免频繁扩容
    new HashMap<>(32, 0.75f);
  2. 使用forEach代替迭代器:

    java 复制代码
    // Java 8+
    list.forEach(System.out::println);
    map.forEach((k, v) -> System.out.println(k + ": " + v));
  3. 避免在循环中修改集合:

    java 复制代码
    // 错误方式 - 可能抛出ConcurrentModificationException
    for (String item : list) {
        if (condition) {
            list.remove(item);
        }
    }
    
    // 正确方式 - 使用迭代器
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        if (condition) {
            it.remove();
        }
    }

3. 常见陷阱

  1. Arrays.asList返回固定大小List:

    java 复制代码
    List<String> list = Arrays.asList("A", "B", "C");
    // list.add("D"); // 抛出UnsupportedOperationException
  2. 集合元素可变性问题:

    java 复制代码
    Set<Date> dates = new HashSet<>();
    Date now = new Date();
    dates.add(now);
    now.setTime(now.getTime() + 1000); // 修改后影响集合行为
  3. equals和hashCode不一致:

    java 复制代码
    class Person {
        String name;
        // 如果只重写equals不重写hashCode,会导致HashSet/HashMap行为异常
    }

十、Java 8-17集合新特性

1. Java 8增强

  • Stream API:函数式集合操作

  • HashMap性能提升:链表转红黑树

  • 新增方法 :

    java 复制代码
    map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
    list.removeIf(e -> e.length() > 5);

2. Java 9增强

  • 工厂方法创建不可变集合 :

    java 复制代码
    List<String> list = List.of("A", "B", "C");
    Set<Integer> set = Set.of(1, 2, 3);
    Map<String, Integer> map = Map.of("A", 1, "B", 2);

3. Java 10增强

  • copyOf创建不可变集合 :

    java 复制代码
    List<String> copy = List.copyOf(originalList);

4. Java 16增强

  • Stream.toList()简化 :

    java 复制代码
    List<String> list = stream.toList(); // 替代collect(Collectors.toList())

通过深入理解Java集合框架的设计原理和使用方法,开发者可以编写出更高效、更健壮的代码。集合框架是Java编程中最常用的工具之一,掌握其特性和最佳实践对提高开发效率至关重要。

相关推荐
anew___6 分钟前
《从零手写操作系统 (20):ELF加载器——让OS读懂现代编译器》
java·服务器·前端
code2cat7 分钟前
【随笔】MCP资源更新订阅:通知到达以后,Agent怎样刷新旧资料
java·后端·开发工具·ai agent·mcp
Source.Liu9 分钟前
【A11】近期实现架构:面向 EPC 工作流企业 QQ 化的第一阶段
windows·架构·rust
全栈练习生12 分钟前
大模型原理之 KV Cache
python·ai
天赐范式24 分钟前
天赐范式第183天:让选择开始生效——育种者方程与选择生效条件
python·数字生命·天赐范式·动态运行时·育种者方程·选择压力·遗传力
benchmark_cc1 小时前
批量行情返回后,怎样把请求失败的股票和正常数据分开?
python·数据分析·pandas·量化交易·股票数据·quantdash
一只旭宝1 小时前
C++ 后端开发面试题整理
java·c++·面试
sunshine22 girl1 小时前
Java学习五 面向对象高级5 内部类3-静态内部类和局部内部类(了解)
java·学习
en.en..1 小时前
Linux 进程退出exit(函数)
java·开发语言·算法
李游Leo1 小时前
HarmonyOS 7 TaskPool + Node-API + zstd:Native 批量压缩任务的主线程隔离、进度回传与资源收口【鸿蒙心迹】
java·华为·harmonyos