system.arraycopy本身不直接分割数组,而是通过批量、精准搬运原数组各切片到预分配的多个目标数组中实现高效分割;需提前创建子数组、精确计算每段偏移与长度、确保类型严格兼容,且chunksize建议≥256以发挥simd优化优势。

System.arraycopy 本身不直接“分割”数组,它只做片段搬运——但正因如此,它是实现高效、可控数组分割的底层核心工具。真正要完成“大规模数组分割”,关键不是调用一次 arraycopy,而是用它批量、精准地把原数组的不同切片,分别复制到多个目标数组中。
分割前必须明确三件事
-
目标数组得提前准备好:不能靠
arraycopy分配内存,每个子数组都要new int[chunkSize]或类似方式创建好。 -
每段长度和偏移要算准:比如原数组长 100_000,按每块 8192 切,最后一块是
100_000 % 8192 = 1632,不能硬写8192导致越界。 -
类型必须一致且兼容:
byte[]只能分给byte[]子数组;若想转成Object[],需确保源是引用类型(如String[]),否则ArrayStoreException立刻报错。
高效分割的典型写法
适用于日志解析、网络包拆帧、批量数据分片等场景:
- 先计算总块数:
int chunks = (src.length + chunkSize - 1) / chunkSize; - 创建结果容器:
byte[][] chunksArray = new byte[chunks][]; - 循环填充每一块:
for (int i = 0; i
为什么不用 Arrays.copyOf 或流式切分?
-
Arrays.copyOfRange内部虽也调arraycopy,但每次调用都新建数组+校验,在循环中反复调用,开销叠加明显;手动控制new byte[len]+arraycopy更轻量。 -
Stream.of().skip().limit()看似简洁,但会 boxing、迭代器开销大,百万级数据下慢 5–10 倍,且无法复用缓冲区。 - 若需复用固定大小缓冲池(如 NIO
ByteBuffer场景),直接arraycopy到预分配的byte[8192]中,再标记有效长度,零对象创建。
大规模分割的性能要点
-
chunkSize 设为 256 起更划算:实测表明,单块 ≤ 64 字节时,
arraycopy的 JNI 进入开销可能超过收益;推荐设为 1024 或 4096,便于 CPU 向量化搬运。 - 避免跨代拷贝干扰 GC:若源数组在老年代,目标子数组在新生代,JVM 仍需走 write barrier;尽量让所有数组在同一代(如全用堆外或全用年轻代)。
- 多线程分割时,别共用同一 dest 数组:每个线程应操作独立子数组,最后合并;若强行并发写不同偏移,缓存行竞争会导致性能反降。
不复杂但容易忽略











