NIUCLOUD是一款SaaS管理后台框架多应用插件+云编译。上千名开发者、服务商正在积极拥抱开发者生态。欢迎开发者们免费入驻。一起助力发展! 广告
在 Java 中,这四者可以分为两大阵营:**线性容器**(数组、List)和**键值对容器**(Map、HashMap)。 * * * ### 1\. 核心区别对比 | **特性** | **数组 (Array)** | **List (如 ArrayList)** | **Map (接口)** | **HashMap (实现类)** | | --- | --- | --- | --- | --- | | **存储结构** | 连续的内存空间 | 动态数组(底层是数组) | 键值对 (Key-Value) | 哈希表 (数组+链表/红黑树) | | **长度/容量** | **固定**,创建后不可变 | **动态**,自动扩容 | 动态扩容 | 动态扩容 | | **访问方式** | 通过 **索引** (0, 1...) | 通过 **索引** 或 迭代器 | 通过 **键 (Key)** 获取值 | 通过 **键 (Key)** 获取值 | | **存储类型** | 基本类型 & 引用类型 | 仅限引用类型 | 仅限引用类型 | 仅限引用类型 | | **重复性** | 允许重复值 | 允许重复值 | **Key 唯一**,Value 可重复 | Key 唯一,Value 可重复 | * * * ### 2\. 详细拆解与示例 #### **数组 (Array)** Java 最底层的容器。速度最快,但灵活性最差。 * **适用场景**:已知固定数量的元素,追求极致性能。 * **示例**: Java ~~~ // 定义一个长度为 3 的字符串数组 String[] names = new String[3]; names[0] = "张三"; names[1] = "李四"; // names.length 获取长度 (属性) ~~~ #### **List (集合/列表)** 最常用的线性容器,你可以把它看作是“加强版”的数组。 * **适用场景**:需要按顺序存储元素,且元素个数会变动(如:查出来的账单列表)。 * **示例**: Java ~~~ List<String> list = new ArrayList<>(); list.add("张三"); list.add("李四"); list.add("张三"); // 允许添加重复元素 // list.get(0) 获取第一个元素 ~~~ #### **Map 与 HashMap** Map 是接口(定义了标准),HashMap 是 Map 接口最常用的实现类。 它们不按索引存,而是按“映射关系”存。 * **适用场景**:需要通过一个唯一标识(如学号、ID)快速查找数据。 * **示例**: Java ~~~ // Map 是接口声明,HashMap 是具体实例化 Map<String, Integer> scoreMap = new HashMap<>(); scoreMap.put("张三", 90); scoreMap.put("李四", 85); scoreMap.put("张三", 100); // Key 唯一:这会覆盖掉之前的 90 分 System.out.println(scoreMap.get("张三")); // 输出 100 ~~~ * * * ### 3\. 形象比喻 * **数组/List**:像一排有编号的**储物柜**。你想找东西,得记住它在几号柜子(索引)。 * **Map/HashMap**:像一本**字典**。你想找解释(Value),只需要搜索对应的单词(Key)。你不需要知道这个词在字典的第几页。 * * * ### 4\. 总结与选型建议 1. **如果你需要存一串东西,且经常要增删、不确定多少个**:选 **`List`** (通常是 `ArrayList`)。 2. **如果你需要通过某个“名字”或“ID”快速翻找东西**:选 **`HashMap`**。 3. **如果你处理的是非常底层的坐标、字节流,且长度永远不变**:选 **`数组`**。 **有趣的一点:** 在你最初的业务代码里,我们将 `billId` 字符串 `split` 成了 **数组**,随后为了方便统计结果,我们创建了一个 **HashMap**。这正好体现了它们各自的用处。 需要我为你演示一下如何用 **Map** 来优化那些复杂的“双重 for 循环”查询吗?(这是面试中非常常见的性能优化点)