In a previous question Why clone() is the best way for copying arrays? @procrastinator demonstrates that given an array, original.clone()
is in average two times faster than System.arraycopy(original, 0, destination, 0, length)
However I have noticed that when using the clone
method it is not possible to modify the length of the destination array, nor copy only a portion of the array. Using System.arraycopy
I would do:
New array with extra positions
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;
New array with less positions
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)
(Notice that the arrays in the example are small for the sake of clarity but in the real case they are bigger)
Is there a way to achieve a similar performance to clone
in any of the scenarios? Or in these cases we must use the System.arraycopy
method?
EDIT1 :
As suggested by @aUserHimself I have tried (without any success) to measure the performance of the System.arraycopy
against the Stream
interface. Below I provide the Benchmark code and its results:
@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;
}
Results:
Benchmark (size) Mode Cnt Score Error Units
SampleBenchmark.StreamArraycopyBigger 10000 thrpt 10 ≈ 0 ops/s
SampleBenchmark.StreamArraycopyBigger 1000 thrpt 10 ≈ 0 ops/s
SampleBenchmark.StreamArraycopyBigger 100 thrpt 10 11,997 ± 0,002 ops/s
SampleBenchmark.StreamArraycopyBigger 10 thrpt 10 608,899 ± 8,975 ops/s
SampleBenchmark.StreamArraycopyBigger 1 thrpt 10 6373,457 ± 313,626 ops/s
SampleBenchmark.StreamArraycopySmaller 10000 thrpt 10 36,692 ± 0,728 ops/s
SampleBenchmark.StreamArraycopySmaller 1000 thrpt 10 328,875 ± 2,259 ops/s
SampleBenchmark.StreamArraycopySmaller 100 thrpt 10 2141,368 ± 8,832 ops/s
SampleBenchmark.StreamArraycopySmaller 10 thrpt 10 9018,659 ± 118,933 ops/s
SampleBenchmark.StreamArraycopySmaller 1 thrpt 10 12954,709 ± 114,621 ops/s
SampleBenchmark.SystemArraycopyBigger 10000 thrpt 10 ≈ 0 ops/s
SampleBenchmark.SystemArraycopyBigger 1000 thrpt 10 ≈ 0 ops/s
SampleBenchmark.SystemArraycopyBigger 100 thrpt 10 161,004 ± 1,361 ops/s
SampleBenchmark.SystemArraycopyBigger 10 thrpt 10 10039,397 ± 123,553 ops/s
SampleBenchmark.SystemArraycopyBigger 1 thrpt 10 42539,869 ± 1965,589 ops/s
SampleBenchmark.SystemArraycopySmaller 10000 thrpt 10 399,816 ± 6,503 ops/s
SampleBenchmark.SystemArraycopySmaller 1000 thrpt 10 3189,271 ± 117,936 ops/s
SampleBenchmark.SystemArraycopySmaller 100 thrpt 10 22533,102 ± 183,870 ops/s
SampleBenchmark.SystemArraycopySmaller 10 thrpt 10 45577,443 ± 1656,788 ops/s
SampleBenchmark.SystemArraycopySmaller 1 thrpt 10 41657,519 ± 183,266 ops/s
Does anyone know about any other possible approach?
EDIT2 :
I have updated the benchmark codes and results with the suggested modifications to make the comparison even. However, for the bigger experimentation there is some error (probably due to the heap size I suppose) and for the smaller experimentation the Arraycopy
still outperforms the Stream
one. So I suppose there is no better way to copy arrays when the destination differs on size than using arraycopy
.