Java原生数组长度不可变,动态调整本质是创建新数组、复制数据、更新引用;频繁增删应优先用ArrayList,手动模拟仅适用于底层控制或教学;扩容用Arrays.copyOf或System.arraycopy,缩容用Arrays.copyOf截取前N个元素。

Java 中原生数组长度不可变,所谓“动态调整”本质是创建新数组、复制数据、更新引用。真正需要频繁增删的场景,应优先用 ArrayList;若需底层控制或教学演示,才考虑手动模拟扩容缩容。
一维数组的手动扩容与缩容
固定数组要“变长”,只能新建更大数组并迁移数据:
- 用 Arrays.copyOf(arr, newSize) 最简洁:自动处理复制和默认值填充(如 int 数组新增位置补 0)
- 用 System.arraycopy() 更精细:可指定源/目标起始位置和长度,适合部分复制或移动
- 缩容不是“删长度”,而是 Arrays.copyOf(arr, newSmallerSize) —— 只保留前 N 个有效元素,多余内存由 GC 回收
- 注意:每次操作都生成新数组,原数组若无其他引用即被丢弃,频繁调用会影响性能
封装 DynamicArray 工具类的关键点
自己写动态数组工具类时,容易踩坑,核心在于状态一致性:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不要同时维护 array.length 和额外的 size 字段——二者语义不同:length 是底层数组容量,size(或更准确叫 pointer)才是已存元素个数
- add 方法中,先判断 pointer == array.length 再扩容,扩容后更新的是 array 引用,不是 size
- 遍历时用 for (int i = 0; i ,而非 i ,避免打印未使用的默认值
- 泛型支持需绕过类型擦除:内部用 Object[] 存储,get 时强制转型,或用反射创建数组(但有运行时开销)
ArrayList 是更优解,不是替代方案
别为了“练手”在生产环境重复造轮子:
立即学习“Java免费学习笔记(深入)”;
- add/remove 自动触发扩容/缩容:默认 1.5 倍增长,阈值与批量复制已优化多年
- trimToSize() 可主动释放冗余空间;ensureCapacity(n) 预留容量避免多次扩容
- 它还提供线程安全包装(Collections.synchronizedList)、只读视图、fail-fast 迭代器等成熟机制
- 真要转成数组?用 list.toArray(new Type[list.size()]),类型安全且高效
何时该用数组,何时该用集合
选择取决于数据生命周期和操作模式:
- 纯计算中间结果、大小确定且只读 → 原生数组更轻量、缓存友好
- 频繁 add/remove、不确定最终大小、需查找/排序/去重 → ArrayList 或 LinkedList 更合适
- 需要键值映射、唯一性约束、并发访问 → 跳过数组,直接选 HashMap、TreeSet 等集合
- 性能敏感场景(如高频数值运算),可配合 primitive collections 库(如 Eclipse Collections)避免装箱开销

















