|
@@ -239,6 +239,79 @@ Vector LinkedHashSet
|
|
|
|
|
|
|
|
> 📄 来源:`collection/Demo02.java`
|
|
> 📄 来源:`collection/Demo02.java`
|
|
|
|
|
|
|
|
|
|
+### 2.4 ArrayList 底层实现详解
|
|
|
|
|
+
|
|
|
|
|
+`ArrayList` 是 `List` 接口最常用的实现类,底层使用**可变数组**(动态数组)存储数据。
|
|
|
|
|
+
|
|
|
|
|
+#### 2.4.1 核心特性
|
|
|
|
|
+
|
|
|
|
|
+- **本质**:长度可变的数组,底层维护的是一个 `Object[] elementData`
|
|
|
|
|
+- **允许存储 `null`**
|
|
|
|
|
+- 和 `Vector` 类似,但**不是线程同步的**(非线程安全),性能更高
|
|
|
|
|
+- 内部维护一个 `size` 属性,表示数组中**有效元素的个数**(不是数组长度)
|
|
|
|
|
+- `size()` 方法返回 `size` 属性
|
|
|
|
|
+- `isEmpty()` 返回 `size == 0`
|
|
|
|
|
+
|
|
|
|
|
+> 📄 来源:`collection/Demo02.java`
|
|
|
|
|
+
|
|
|
|
|
+#### 2.4.2 默认容量与扩容机制
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+// 默认初始容量为 10
|
|
|
|
|
+private static final int DEFAULT_CAPACITY = 10;
|
|
|
|
|
+
|
|
|
|
|
+// 空数组(用户指定容量为 0 时使用)
|
|
|
|
|
+private static final Object[] EMPTY_ELEMENTDATA = {};
|
|
|
|
|
+
|
|
|
|
|
+// 默认容量空数组(无参构造时使用)
|
|
|
|
|
+private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
|
|
|
|
|
+
|
|
|
|
|
+// 底层维护的数组
|
|
|
|
|
+transient Object[] elementData;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**扩容流程:**
|
|
|
|
|
+1. 使用无参构造时,`elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA`(容量为 0 的空数组)
|
|
|
|
|
+2. 第一次添加元素时,立即将容量**扩容到 `DEFAULT_CAPACITY`(10)**
|
|
|
|
|
+3. 后续元素超出容量时,自动按 **1.5 倍** 扩容(`oldCapacity + (oldCapacity >> 1)`)
|
|
|
|
|
+
|
|
|
|
|
+#### 2.4.3 三个构造方法
|
|
|
|
|
+
|
|
|
|
|
+| 构造方法 | 说明 |
|
|
|
|
|
+|----------|------|
|
|
|
|
|
+| `ArrayList()` | 无参构造,`elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA`(初始容量 0,首次添加时扩容到 10) |
|
|
|
|
|
+| `ArrayList(int initialCapacity)` | 指定初始容量,若大于 0 则 `elementData = new Object[initialCapacity]`;若为 0 则 `elementData = EMPTY_ELEMENTDATA` |
|
|
|
|
|
+| `ArrayList(Collection<? extends E> c)` | 传入另一个集合对象,将其所有元素添加到新建的 `ArrayList` 中 |
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+// 无参构造 — 默认容量 10(懒加载,首次 add 时扩容)
|
|
|
|
|
+ArrayList list01 = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+// 指定初始容量为 20
|
|
|
|
|
+ArrayList list02 = new ArrayList<>(20);
|
|
|
|
|
+
|
|
|
|
|
+// 以另一个集合为参数创建
|
|
|
|
|
+ArrayList list03 = new ArrayList<>(list02);
|
|
|
|
|
+
|
|
|
|
|
+System.out.println(list01.size()); // 0
|
|
|
|
|
+System.out.println(list02.size()); // 0
|
|
|
|
|
+System.out.println(list03.size()); // 0
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+> 📄 来源:`collection/Demo02.java`
|
|
|
|
|
+
|
|
|
|
|
+#### 2.4.4 关键属性速查
|
|
|
|
|
+
|
|
|
|
|
+| 属性/方法 | 说明 |
|
|
|
|
|
+|-----------|------|
|
|
|
|
|
+| `DEFAULT_CAPACITY = 10` | 默认初始容量 |
|
|
|
|
|
+| `elementData` | 底层维护的 `Object[]` 数组 |
|
|
|
|
|
+| `size` | 有效元素的个数(非数组长度) |
|
|
|
|
|
+| `size()` | 返回 `size` 属性 |
|
|
|
|
|
+| `isEmpty()` | 返回 `size == 0` |
|
|
|
|
|
+
|
|
|
|
|
+> 💡 **注意**:`ArrayList` 的 `size` 是元素个数,`elementData.length` 才是数组的物理容量(`capacity`),二者不一定相等。`size <= capacity` 恒成立。
|
|
|
|
|
+
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
## 三、随堂练习要点
|
|
## 三、随堂练习要点
|
|
@@ -252,6 +325,7 @@ Vector LinkedHashSet
|
|
|
| 包装类缓存机制 | -128~127 缓存池,`==` vs `equals()` | — |
|
|
| 包装类缓存机制 | -128~127 缓存池,`==` vs `equals()` | — |
|
|
|
| 集合框架概述 | 集合 vs 数组对比,体系结构 | `collection/Demo01.java` |
|
|
| 集合框架概述 | 集合 vs 数组对比,体系结构 | `collection/Demo01.java` |
|
|
|
| 线性表数据结构 | 栈/队列/数组/链表 特点 | `collection/Demo02.java` |
|
|
| 线性表数据结构 | 栈/队列/数组/链表 特点 | `collection/Demo02.java` |
|
|
|
|
|
+| **ArrayList 底层原理** | **可变数组、默认容量10、扩容机制、三个构造方法、size vs capacity** | `collection/Demo02.java` |
|
|
|
|
|
|
|
|
### 包装类重点
|
|
### 包装类重点
|
|
|
|
|
|
|
@@ -269,6 +343,11 @@ Vector LinkedHashSet
|
|
|
2. **记忆体系结构**:Collection(List / Set)和 Map 两大分支
|
|
2. **记忆体系结构**:Collection(List / Set)和 Map 两大分支
|
|
|
3. **掌握四种线性表结构**:栈(LIFO)、队列(FIFO)、数组(查询快增删慢)、链表(增删快查询慢)
|
|
3. **掌握四种线性表结构**:栈(LIFO)、队列(FIFO)、数组(查询快增删慢)、链表(增删快查询慢)
|
|
|
4. **关联实现类**:`ArrayList` → 数组,`LinkedList` → 链表/队列/栈
|
|
4. **关联实现类**:`ArrayList` → 数组,`LinkedList` → 链表/队列/栈
|
|
|
|
|
+5. **ArrayList 底层细节**:
|
|
|
|
|
+ - 默认容量 10(懒加载,首次 `add` 才扩容)
|
|
|
|
|
+ - 三个构造方法的区别
|
|
|
|
|
+ - `size` 与 `capacity` 的区别:`size` 是元素个数,`capacity` 是数组物理长度
|
|
|
|
|
+ - 允许存储 `null`,非线程安全
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|