当前位置: 首页 > article >正文

Java 容器梳理

Java 的容器框架是语言的核心组成部分,为开发者提供了存储、操作和检索数据的强大工具。本文梳理Java 容器的基础知识、框架结构、核心机制及实用注意事项。


在这里插入图片描述

数组与容器的对比

在 Java 中,存储数据的主要方式是数组容器。二者功能相似,但在以下方面存在显著差异:

  • 大小灵活性

    • 数组的长度固定,创建时确定。
    • 容器的长度可变,可根据需要动态调整。
  • 数据类型

    • 数组可以存储基本数据类型(如 intdouble)和引用数据类型(如对象)。
    • 容器只能存储引用数据类型,基本数据类型需转换为对应的包装类(如 Integer)才能存入。

Java 容器框架

Java 容器框架主要分为两大接口:CollectionMap。以下是其结构概览:

Collection

Collection 表示一组独立的元素序列,受特定规则约束。它分为三个子接口:

  1. List

    • 按插入顺序保存元素。
    • 常见实现:
      • ArrayList:基于动态 Object[] 数组,适合快速随机访问。
      • LinkedList:双向链表(JDK 1.7 后取消循环),适合频繁插入/删除。
      • Vector:通过 synchronized 修饰的线程安全 Object[] 数组。
  2. Set

    • 禁止重复元素。
    • 常见实现:
      • HashSet:无序,基于 HashMap 实现。
      • LinkedHashSet:保持插入顺序,基于 LinkedHashMap
      • TreeSet:按自然顺序或自定义比较器排序,基于红黑树。
  3. Queue

    • 按队列规则组织元素(如 FIFO 或优先级)。
    • 常见实现:
      • PriorityQueue:基于 Object[] 数组的小顶堆。
      • DelayQueue:延迟队列。
      • ArrayDeque:动态数组实现的双端队列。
      • LinkedList:链表形式的双端队列。

Map

Map 管理键值对,键唯一,可通过键查找值。常见实现包括:

  • HashMap
    • JDK 1.8 前:数组 + 链表(通过拉链法解决哈希冲突)。
    • JDK 1.8 后:链表长度超 8(且数组长度 ≥ 64)时转为红黑树,优化查找效率。
  • LinkedHashMap:继承 HashMap,增加双向链表保持插入顺序。
  • Hashtable:线程安全的数组 + 链表结构。
  • TreeMap:基于红黑树,保证键的有序性。

有关框架结构的详细图示,可参考原文档。


容器的核心机制

Java 容器的共性和特性依赖于以下关键机制,理解这些机制有助于掌握其原理和应用。

泛型

Java 1.5 引入泛型,确保容器的类型安全。未使用泛型时,容器可能混杂类型,隐患巨大:

List<Object> list = new ArrayList<>();
list.add("123");
list.add(123); // 字符串和整数混存

使用泛型后,类型检查在编译期完成:

List<String> list = new ArrayList<>();
list.add("123");
// list.add(123); // 编译错误

Iterable 和 Iterator

IterableIterator 接口用于遍历容器元素。Collection 继承 Iterable,所有集合都支持迭代。

  • Iterator 提供 hasNext()next()remove() 等方法。
  • 迭代器模式:标准化遍历,隐藏容器内部实现。

示例:

List<Integer> list = Arrays.asList(1, 2, 3);
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

Fail-Fast 机制:迭代时修改容器结构(如增删元素)可能抛出 ConcurrentModificationException。《阿里巴巴 Java 开发手册》建议避免在 for-each 中直接调用集合的 remove/add,应使用 Iterator 的方法。Java 8+ 还提供 removeIf()

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
list.removeIf(n -> n % 2 == 0); // 删除偶数
System.out.println(list); // [1, 3]

Comparable 和 Comparator

这两个接口用于元素比较和排序:

  • Comparable:类内部实现 compareTo(),排序逻辑与对象绑定。
  • Comparator:外部定义 compare(),灵活性更高。

Comparable 示例:

class User implements Comparable<User> {
    private int age;
    private String name;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(User o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

List<User> users = new ArrayList<>(Arrays.asList(new User("A", 18), new User("B", 17)));
Collections.sort(users); // 按年龄排序

Comparator 示例:

List<User> users = new ArrayList<>(Arrays.asList(new User("A", 18), new User("B", 17)));
Collections.sort(users, Comparator.comparingInt(user -> user.age));

Cloneable

实现**Cloneable** 接口并重写 Object.clone() 可启用对象克隆,否则调用 clone() 会抛出 CloneNotSupportedException。默认 clone() 为浅拷贝,深拷贝需自定义实现。

Fail-Fast 机制

Fail-Fast 是 Java 容器的错误检测机制,迭代时若结构被修改(如增删元素),可能抛出 ConcurrentModificationException。示例:

List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) list.add(i);

new Thread(() -> {
    Iterator<Integer> it = list.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
        try { Thread.sleep(100); } catch (Exception e) {}
    }
}).start();

new Thread(() -> {
    for (int i = 0; i < 10; i++) if (i % 2 == 0) list.remove(i);
}).start();

解决方法

  • 使用同步(如 synchronizedCollections.synchronizedList),但可能影响性能。
  • 使用并发容器,如 CopyOnWriteArrayList

容器与线程安全

为在并发环境中安全使用容器,Java 提供:

  • 同步容器:如 VectorHashtableCollections.synchronizedXXX 包装。
  • 并发容器:位于 java.util.concurrent,如 ConcurrentHashMapCopyOnWriteArrayList

总结

Java 容器通过泛型、迭代器、比较器和错误检测机制(如 fail-fast),提供了高效、类型安全和线程安全的解决方案。从有序的 List、无重复的 Set 到键值对的 Map,理解这些机制能让你编写更健壮的代码。


http://www.kler.cn/a/568407.html

相关文章:

  • 分布式拒绝服务(DDoS)攻击检测系统的设计与实现
  • 基金 word-->pdf图片模糊的解决方法
  • MATLAB代码:机器学习-分类器
  • RAG项目实战:金融问答系统
  • 物联网同RFID功能形态 使用场景的替代品
  • Android 图片压缩详解
  • python中单例模式应用
  • 【计算机网络入门】初学计算机网络(九)
  • 2025年2月最新一区SCI-海市蜃楼搜索优化算法Mirage search optimization-附Matlab免费代码
  • 蓝桥杯 灯笼大乱斗【算法赛】
  • android智能指针android::sp使用介绍
  • Pytorch为什么 nn.CrossEntropyLoss = LogSoftmax + nn.NLLLoss?
  • 使用Docker快速搭建Redis主从复制
  • 【硬件工程师成长】之是否需要组合电容进行滤波的考虑
  • PDF工具 Candy Desktop(安卓)
  • openharmony-音频
  • HideUL:守护电脑隐私,轻松隐藏软件的隐藏工具
  • 京东一面:为什么 IDEA 建议去掉 StringBuilder,而要使用 “+” 拼接字符串?
  • 人工智能核心技术初识:Prompt、RAG、Agent与大模型微调
  • ECharts组件封装教程:Vue3中的实践与探索