Java 目标阵列大小不同时System.arraycopy的替代方案

Java 目标阵列大小不同时System.arraycopy的替代方案,java,arrays,copy,clone,Java,Arrays,Copy,Clone,在前面的一个问题中,@dellautiator演示了给定一个数组,original.clone()平均比System.arraycopy(original,0,destination,0,length)快两倍。 但是,我注意到,当使用克隆方法时,无法修改目标阵列的长度,也无法仅复制阵列的一部分。使用System.arraycopy我会: 具有额外位置的新阵列 int[] original = new int[] {1,2,3,4,5}; int originalSize = original.l

在前面的一个问题中,@dellautiator演示了给定一个数组,
original.clone()
平均比
System.arraycopy(original,0,destination,0,length)快两倍。

但是,我注意到,当使用
克隆
方法时,无法修改目标阵列的长度,也无法仅复制阵列的一部分。使用
System.arraycopy
我会:

具有额外位置的新阵列

int[] original = new int[] {1,2,3,4,5};
int originalSize = original.length;
int newSize = originalSize + 1;
int[] destination = new int[newSize];

System.arraycopy(original, 0, destination, 0)
destination[newSize - 1] = newValue;
int[] original = new int[] {1,2,3,4,5};
int originalSize = original.length;
int newSize = originalSize - 1;
int[] destination = new int[newSize];

System.arraycopy(original, 1, destination, 0)
位置较少的新阵列

int[] original = new int[] {1,2,3,4,5};
int originalSize = original.length;
int newSize = originalSize + 1;
int[] destination = new int[newSize];

System.arraycopy(original, 0, destination, 0)
destination[newSize - 1] = newValue;
int[] original = new int[] {1,2,3,4,5};
int originalSize = original.length;
int newSize = originalSize - 1;
int[] destination = new int[newSize];

System.arraycopy(original, 1, destination, 0)
(请注意,为了清晰起见,示例中的数组较小,但在实际情况中,它们较大)

在任何情况下,是否有办法实现与克隆类似的性能?或者在这些情况下,我们必须使用
System.arraycopy
方法

EDIT1: 正如@aUserHimself所建议的,我已经尝试(没有任何成功)根据
接口测量
系统.arraycopy
的性能。下面我提供了基准代码及其结果:

@Benchmark
public int[] SystemArraycopySmaller() {
    final int length = this.size;
    int[] destination = new int[length / 2];
    System.arraycopy(this.original, 0, destination, 0, length / 2);
    return destination;
}

@Benchmark
public int[] StreamArraycopySmaller() {
    final int length = this.size;
    int[] destination = Arrays.stream(this.original).filter(i -> i < length / 2).toArray();
    return destination;
}

@Benchmark
public int[] SystemArraycopyBigger() {
    final int length = this.size;
    int[] destination = new int[length * length];
    for (int i = 0; i < length; i++) {
        System.arraycopy(this.original, 0, destination, i * length, length);
    }
    return destination;
}

@Benchmark
public int[] StreamArraycopyBigger() {
    int[] destination = Arrays.stream(this.original).flatMap(i -> Arrays.stream(this.original).map(j -> j)).toArray();
    return destination;
}
有人知道其他可能的方法吗

EDIT2:
我已经用建议的修改更新了基准代码和结果,以使比较更加公平。但是,对于较大的实验,存在一些错误(可能是由于堆的大小),对于较小的实验,
Arraycopy
仍然优于
因此,我认为当目标大小不同时,没有比使用
arraycopy

更好的复制数组的方法了。您也可以尝试根据
java8
来衡量性能,当您需要筛选出目标数组或向
目标数组添加新元素时,该方法非常有用:

public static void copyBigArrayAndFilter() {
    long time = System.currentTimeMillis();
    int[] original = IntStream.range(0, 10_000).toArray();
    int[] destination = Arrays.stream(original).filter(i -> i > 1_000 && i < 9_000).toArray();
    System.out.println("Original size: " + original.length);
    System.out.println("Destination size: " + destination.length);
    System.out.println("Duration: " + (System.currentTimeMillis() - time) + " ms." );
}

public static void copyBigArrayAndAdd() {
    long time = System.currentTimeMillis();
    int[] original = IntStream.range(0, 10_000).toArray();
    int[] destination = Arrays.stream(original).flatMap(i -> Arrays.stream(original).map(j -> i + j)).toArray();
    System.out.println("Original size: " + original.length);
    System.out.println("Destination size: " + destination.length);
    System.out.println("Duration: " + (System.currentTimeMillis() - time) + " ms." );
}

我不确定这是你想要的。但我想指出的是:如果您已经处理了数组,那么与
System.arraycopy
相比,您几乎没有机会做得更好。但是,如果您需要修改/处理并只复制其中的一部分,
streams
可能会更快。

@nullpointer谢谢。看到我更新的问题我会说不,没有办法达到与克隆类似的性能。还有
Arrays.copyOf
,但它只在内部使用
arraycopy
。当然,如果您的性能热点在复制数组,也许你使用了错误的工作语言?@Kayaman这不是我项目中唯一的性能问题,但假设我目前无法更改语言,因为我受益于其他Java实用程序(该项目有10万loc)这是您的项目中最重要的性能问题吗?正如建议的那样,我已被标记为反对
接口,但没有成功。我对它不是很熟悉,但效果很差。你能检查一下我更新的答案,看看我是否遗漏了什么吗?@CristianRamon Cortes你正在对不同的操作进行基准测试(在时间成本和效率方面),我的
流中有一些额外的步骤
示例显然比你的简单副本更耗时。请参阅上面的更新,以便获得更准确的结果。我已经用新的基准和结果更新了问题。尽管
arraycopy
仍然优于
stream
实现,但我认为没有其他方法,因此我会将您的答案标记为已接受,因为它提供了将
arraycopy
stream
进行比较的解决方案。