集合家族详情

一、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()方法

相关推荐
真的想上岸啊6 分钟前
学习C++、QT---18(C++ 记事本项目的stylesheet)
开发语言·c++·学习
明天好,会的13 分钟前
跨平台ZeroMQ:在Rust中使用zmq库的完整指南
开发语言·后端·rust
丁劲犇1 小时前
用 Turbo Vision 2 为 Qt 6 控制台应用创建 TUI 字符 MainFrame
开发语言·c++·qt·tui·字符界面·curse
旷世奇才李先生1 小时前
Next.js 安装使用教程
开发语言·javascript·ecmascript
木头没有瓜1 小时前
idea离线安装插件
java·ide·intellij-idea
llwszx1 小时前
Spring中DelayQueue深度解析:从原理到实战(附结构图解析)
java·后端·spring·delayqueue·延迟任务
述雾学java2 小时前
Spring Cloud Feign 整合 Sentinel 实现服务降级与熔断保护
java·spring cloud·sentinel
保持学习ing2 小时前
苍穹外卖day3--公共字段填充+新增菜品
java·阿里云·实战·springboot·前后端·外卖项目·阿里云文件存储
charlie1145141912 小时前
深入理解Qt的SetWindowsFlags函数
开发语言·c++·qt·原理分析
77qqqiqi2 小时前
正则表达式
java·后端·正则表达式