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编程中最常用的工具之一,掌握其特性和最佳实践对提高开发效率至关重要。

相关推荐
2301_780789668 小时前
跨平台适配!SDK 游戏盾兼容全终端游戏场景
java·网络·ddos
第九序言T8 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
Java后端的Ai之路9 小时前
CAS并发控制-从CPU指令到企业级乐观锁
vue.js·人工智能·python·cas·乐观锁
qq_426003969 小时前
UI自动化高频次登录login限流解决方案
python·ui·自动化
Sakura_j_h_9 小时前
EasyEDA PCB 快速设计Skills
c++·python·github
学长毕设9 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
步行cgn10 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川10 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵10 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
quantdash_cc10 小时前
如何验证历史行情的交易日期是否完整覆盖研究区间?
python·数据分析·pandas·量化交易·股票数据·quantdash