AbstractList 本身不能直接实现虚拟数组视图,它只是提供 List 骨架的抽象基类;真正实现需继承它并重写 size() 和 get(int) 方法,按需计算元素以节省内存。
abstractlist 本身不能直接实现虚拟数组视图,它只是一个抽象基类,提供 list 接口的骨架实现,但不负责内存优化或延迟加载。真正能帮你节省物理内存、构建“虚拟数组视图”的,是**继承 abstractlist 并重写关键方法(尤其是 get(int) 和 size())**,让元素按需计算/加载,而非全部预分配存储。
核心思路:用逻辑索引代替真实存储
虚拟数组视图的本质是:对外表现得像一个普通 List(支持 get、size、迭代等),但内部不保存所有元素,而是根据下标实时生成或查取数据。比如表示一个长度为 100 万的“全零数组”、一个等差数列、或一个映射到磁盘/数据库的超大集合。
AbstractList 的默认实现依赖于 get(int) 和 size(),只要这两个方法高效且不触发全量加载,其余方法(如 iterator()、subList())就能自动获得正确行为(因为 AbstractList 已为你实现了这些的委托逻辑)。
关键实现步骤
- 继承
AbstractList,声明你的泛型类型(如Integer、String) - 重写
public int size()—— 返回逻辑长度(例如 10_000_000),不分配内存 - 重写
public E get(int index)—— 根据 index 实时计算或加载单个元素,避免缓存整个数组 - (可选)重写
public boolean contains(Object o)或indexOf等,若默认线性扫描不满足性能需求
简单示例:虚拟的等差数列视图
(Java)```java
public class ArithmeticSequenceView extends AbstractList
private final int start;
private final int step;
private final int size;
public ArithmeticSequenceView(int start, int step, int size) {
this.start = start;
this.step = step;
this.size = Math.max(0, size);
}
@Override
public int size() {
return size;
}
@Override
public Integer get(int index) {
if (index = size) {
throw new IndexOutOfBoundsException();
}
return start + index * step;
}
}
```
使用它:
List<integer> seq = new ArithmeticSequenceView(10, 3, 1_000_000);<br>System.out.println(seq.get(999999)); // 输出 3000007,无需创建百万个 Integer 对象</integer>
进阶提示:结合实际场景优化
- 若底层数据来自文件或网络,
get(int)可做随机读取(如 Memory-Mapped File),避免加载整块 - 可配合
RandomAccess标记接口(让 Collections.binarySearch 等算法更高效) - 注意线程安全:AbstractList 非线程安全,如需并发访问,应在
get()内部加锁或使用不可变逻辑 - 避免在
get()中做重操作(如每次 HTTP 请求);必要时引入局部缓存(如 LRU 缓存最近 N 个),但要控制缓存大小,防止内存失控











