跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何在 Java 中正确实现动态数组的扩容机制

本文详解 java 中自定义动态数组类的扩容逻辑,重点解决因未同步更新容量字段导致的扩容失效问题,并提供可直接运行的修复代码与最佳实践建议。 在 Java 中,原生数组(int[])是固定长度的,无法直接“改变大小”。因此,实现一个类似 ArrayList 的动态数组类时,核心在于:当容量不足时, 创建一个更大的新数组 → 将旧数据复制过去 → 用新数组替换旧引用 。但仅完成内存分配和数据拷贝还不够——若未同步更新用于容量判断的字段,扩容将形同虚设。 观察原始代码,问题根源在于 resize() 方法中:
private void resize() { int[] temp = new int[size * 2]; // ❌ 错误:仍用过时的 size 字段计算新容量 for (int i = 0; i < array.length; i++) { temp[i] = array[i]; } array = temp; // ✅ 正确:完成引用切换 // ❌ 缺失:未更新 size 字段!后续 isFull() 仍按旧 size 判断 }
由于 size 始终保持初始值(如 5),isFull() 方法实际比较的是 pointer == array.length(即当前物理容量),而 resize() 却用恒定的 size * 2 创建新数组——这看似“扩容”,但下次 isFull() 仍会立即返回 true,因为 pointer 已达旧长度,而 size 未变,导致无限扩容循环或逻辑错乱。 ✅ 正确做法是:移除冗余的 size 字段,直接使用 array.length 表示当前容量 。Java 数组对象自带 .length 属性,既准确又无需维护。同时,print() 方法也应遍历有效元素个数(pointer),而非整个数组长度,否则会输出大量默认值 0: Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 立即学习 “ Java免费学习笔记(深入) ”;
public class Array { private int[] array; private int pointer; // 当前已存储元素个数(逻辑大小) private static final int DEFAULT_CAPACITY = 5; public Array() { this(DEFAULT_CAPACITY); } public Array(int initialCapacity) { this.array = new int[initialCapacity]; this.pointer = 0; } public void add(int element) { if (pointer == array.length) { // 直接用 array.length 判断是否满 resize(); } array[pointer++] = element; } private void resize() { int newCapacity = array.length * 2; int[] temp = new int[newCapacity]; System.arraycopy(array, 0, temp, 0, array.length); // 推荐:比手动循环更高效 array = temp; } public void print() { for (int i = 0; i < pointer; i++) { // ✅ 只打印已添加的元素 System.out.println(array[i]); } } // 可选:提供获取当前元素数量的方法 public int size() { return pointer; } // 可选:提供获取当前容量的方法 public int capacity() { return array.length; } }
⚠️ 关键注意事项: 避免维护重复状态 :size 字段与 array.length 语义重叠,易引发不一致;应以 array.length 为唯一容量真相源。 复制效率优先 :使用 System.arraycopy() 替代手动 for 循环,JVM 对其有深度优化。 边界安全 :add() 中先检查再插入,确保 pointer 不越界;print() 使用 pointer 遍历,杜绝无效输出。 命名清晰化 :将 size 字段重命名为 pointer(或 size 表示逻辑大小),更能体现其“已用位置索引”的本质。 通过以上修正,你的 Array 类即可稳定支持自动扩容,行为与 ArrayList 的核心扩容逻辑高度一致——这也是理解 Java 集合框架底层原理的重要一步。

相关文章