集合家族详情

一、Java集合框架全景图

1.1 核心接口层次结构

复制代码
graph TD
    A[Iterable] --> B[Collection]
    B --> C1[List]
    B --> C2[Set]
    B --> C3[Queue]
    C1 --> D1[ArrayList]
    C1 --> D2[LinkedList]
    C2 --> E1[HashSet]
    C2 --> E2[TreeSet]
    C3 --> F1[PriorityQueue]
    G[Map] --> H1[HashMap]
    G --> H2[TreeMap]
    G --> H3[ConcurrentHashMap]

1.2 核心接口说明

接口 特点 典型实现类
List 有序、可重复 ArrayList, LinkedList
Set 无序、唯一 HashSet, TreeSet
Queue 先进先出(FIFO)或优先级队列 LinkedList, PriorityQueue
Map 键值对存储 HashMap, TreeMap
Deque 双端队列 ArrayDeque

二、List家族深度剖析

2.1 ArrayList vs LinkedList

特性 ArrayList LinkedList
底层结构 动态数组 双向链表
随机访问速度 O(1) O(n)
插入删除性能 尾部O(1),中间O(n) 头尾O(1),中间O(n)
内存占用 连续内存,空间浪费少 每个元素额外存储两个指针
最佳场景 高频查询+尾部操作 频繁插入删除(尤其是中间)

代码示例:初始化与遍历

java 复制代码
// ArrayList初始化
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");

// LinkedList初始化
List<String> linkedList = new LinkedList<>();
linkedList.add("C++");
linkedList.addFirst("Go");  // 链表特有方法

// 通用遍历方式(JDK8+)
arrayList.forEach(System.out::println);

三、Set家族的奥秘

3.1 HashSet vs TreeSet

特性 HashSet TreeSet
底层实现 HashMap 红黑树
元素顺序 无序 自然顺序或Comparator排序
时间复杂度 添加/删除/查找平均O(1) 所有操作O(log n)
允许null值 否(除非Comparator支持)

代码示例:自定义对象的HashSet使用

java 复制代码
class Student {
    String id;
    String name;
    // 必须重写equals和hashCode!
    @Override
    public boolean equals(Object o) { /*...*/ }
    @Override
    public int hashCode() { /*...*/ }
}

Set<Student> students = new HashSet<>();
students.add(new Student("1001", "Alice"));

四、Map家族的王者之争

4.1 HashMap底层原理(JDK8+)

  • 数组+链表+红黑树结构

  • 默认负载因子0.75,扩容阈值=容量×负载因子

  • 哈希冲突解决:链表长度≥8时转红黑树,≤6时退化为链表

PUT操作流程示意图:

java 复制代码
ConcurrentMap<String, Integer> scores = new ConcurrentHashMap<>();
scores.compute("Alice", (k, v) -> (v == null) ? 1 : v + 1);

五、高级话题与性能优化

5.1 集合初始化容量优化

  • ArrayList:预估数据量避免频繁扩容(默认容量10)

  • HashMap:设置初始容量=预期元素数/0.75 + 1

    java 复制代码
    // 优化示例:预期存储1000个元素
    new HashMap<>( (int)(1000/0.75) + 1 );

5.2 遍历方式的性能对比

遍历方式 ArrayList LinkedList HashSet
for循环 最快 极慢 不支持
迭代器
forEach+lambda

5.3 不可变集合(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("Key1", 1, "Key2", 2);

六、常见问题与陷阱

6.1 ConcurrentModificationException

错误示例:

java 复制代码
List<String> list = new ArrayList<>(Arrays.asList("A", "B"));
for (String s : list) {
    if ("B".equals(s)) {
        list.remove(s);  // 抛出异常!
    }
}

解决方案:

  • 使用迭代器的remove()方法

  • 使用CopyOnWriteArrayList

  • 使用Stream过滤(Java8+)

6.2 hashCode()与equals()的契约

  • 规则1 :两个对象相等(equals()返回true)→ 必须具有相同的hashCode()

  • 规则2hashCode()相同的对象不一定相等

  • 违反后果:在HashSet/HashMap中出现重复元素或丢失元素

七、最佳实践总结

  1. 选择集合类型的三要素

    • 是否需要排序?

    • 是否需要唯一性?

    • 主要操作类型(查询/插入/删除)?

  2. 线程安全策略

    • 无竞争:普通集合

    • 低竞争:Collections.synchronizedXXX()

    • 高并发:ConcurrentHashMap, CopyOnWriteArrayList

  3. 性能黄金法则

    • 预估容量减少扩容

    • 避免在循环中频繁创建迭代器

    • 复杂对象实现高效的hashCode()方法

相关推荐
郝学胜-神的一滴4 分钟前
基于C++的词法分析器:使用正则表达式的实现
开发语言·c++·程序人生·正则表达式·stl
还是鼠鼠22 分钟前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
Xiaokai丶1 小时前
Java 8 新特性深度剖析:核心要点与代码实战
java
灵魂猎手1 小时前
3. MyBatis Executor:SQL 执行的核心引擎
java·后端·源码
Galaxy在掘金1 小时前
从业8年,谈谈我认知的后端架构之路-1
java·架构
努力努力再努力wz1 小时前
【c++深入系列】:万字详解模版(下)
java·c++·redis
林开落L2 小时前
库的制作与原理
linux·开发语言·动静态库·库的制作
m0_480502642 小时前
Rust 入门 泛型和特征-特征对象 (十四)
开发语言·后端·rust
瓦特what?3 小时前
关于C++的#include的超超超详细讲解
java·开发语言·数据结构·c++·算法·信息可视化·数据挖掘
祁同伟.3 小时前
【C++】动态内存管理
开发语言·c++