Reputation: 29864
In an effort to reduce mutability, should we rather use
public void setValues(String[] newVals) {
this.vals = ( newVals == null ? null : newVals.clone() );
}
or
public void setValues(String[] newVals) {
this.vals = ( newVals == null ? null : Arrays.copyOf(newVals, newVals.length) );
}
Upvotes: 51
Views: 50698
Reputation: 328737
Using jmh, I get similar results, except that clone
seems to be marginally better.
I ran a quick test for performance: clone
, System.arrayCopy
and Arrays.copyOf
have very similar performance (jdk 1.7.06, server vm).
For details (in ms), after JIT:
clone: 68
arrayCopy: 68
Arrays.copyOf: 68
Test code:
public static void main(String[] args) throws InterruptedException,
IOException {
int sum = 0;
int[] warmup = new int[1];
warmup[0] = 1;
for (int i = 0; i < 15000; i++) { // triggers JIT
sum += copyClone(warmup);
sum += copyArrayCopy(warmup);
sum += copyCopyOf(warmup);
}
int count = 10_000_000;
int[] array = new int[count];
for (int i = 0; i < count; i++) {
array[i] = i;
}
// additional warmup for main
for (int i = 0; i < 10; i++) {
sum += copyArrayCopy(array);
}
System.gc();
// copyClone
long start = System.nanoTime();
for (int i = 0; i < 10; i++) {
sum += copyClone(array);
}
long end = System.nanoTime();
System.out.println("clone: " + (end - start) / 1000000);
System.gc();
// copyArrayCopy
start = System.nanoTime();
for (int i = 0; i < 10; i++) {
sum += copyArrayCopy(array);
}
end = System.nanoTime();
System.out.println("arrayCopy: " + (end - start) / 1000000);
System.gc();
// copyCopyOf
start = System.nanoTime();
for (int i = 0; i < 10; i++) {
sum += copyCopyOf(array);
}
end = System.nanoTime();
System.out.println("Arrays.copyOf: " + (end - start) / 1000000);
// sum
System.out.println(sum);
}
private static int copyClone(int[] array) {
int[] copy = array.clone();
return copy[copy.length - 1];
}
private static int copyArrayCopy(int[] array) {
int[] copy = new int[array.length];
System.arraycopy(array, 0, copy, 0, array.length);
return copy[copy.length - 1];
}
private static int copyCopyOf(int[] array) {
int[] copy = Arrays.copyOf(array, array.length);
return copy[copy.length - 1];
}
Upvotes: 44
Reputation: 657
Please also consider the security of using "clone()". A class of well-known attacks use classes that override objects' "clone()" methods with malicious code. For example, CVE-2012-0507 (the "Flashback" attack on Mac OS) was addressed by basically replacing a ".clone()" call with a ".copyOf" call.
Additional discussion on the obsolete-ness of "clone()" can be found on StackOverflow here: object cloning with out implementing cloneable interface
Upvotes: 7
Reputation: 19185
I written a simple program to check the difference.
public static void main(String[] args) throws IOException, InterruptedException,
PrinterException
{
//Verify array remains immutable.
String[] str = {"a","b","c"};
String[] strings = str.clone();
//change returned array
strings[2]= "d";
System.out.println(Arrays.toString(str));
System.out.println(Arrays.toString(strings));
String[] stringsCopy = Arrays.copyOf(str, str.length);
stringsCopy[2]= "d";
System.out.println(Arrays.toString(str));
System.out.println(Arrays.toString(stringsCopy));
//peformance
long before = System.currentTimeMillis();
for(int i=0;i<Integer.MAX_VALUE;i++)
{
str.clone();
}
System.out.println("Time Required for Clone: "+ (System.currentTimeMillis()-before));
//peformance
long beforeCopy = System.currentTimeMillis();
for(int i=0;i<Integer.MAX_VALUE;i++)
{
Arrays.copyOf(str, str.length);
}
System.out.println("Time Required for Copy of: "+ (System.currentTimeMillis()-beforeCopy));
}
And it outputs
[a, b, c]
[a, b, d]
[a, b, c]
[a, b, d]
Time Required for Clone: 26288
Time Required for Copy of: 25413
So if you see in both case String[]
is immutable and performance is almost same thought Arrays.copyOf() is slightly faster on my machine.
Update
I changed program to create large array[100 strings] rather than small array.
String[] str = new String[100];
for(int i= 0; i<str.length;i++)
{
str[i]= Integer.toString(i);
}
And moved copy of
method before clone
method. With below results.
Time Required for Copy of: 415095
Time Required for Clone: 428501
Which are again more of same. Please do not ask me to run the test again as it takes a while
:(
Update 2
For String array 1000000
and for number of iterations 10000
Time Required for Copy of: 32825
Time Required for Clone: 30138
copy of
takes more time than clone
Upvotes: 4
Reputation: 12296
In terms of mutability, they will provide exactly the same - shallow copy of data.
Upvotes: 1