lock - synchronized class in java
.clone() o Arrays.copyOf()? (4)
Actualizar usando jmh
Usando jmh , obtengo resultados similares, excepto que el clone
parece ser marginalmente mejor.
Publicación original
System.arrayCopy
una prueba rápida de rendimiento: clone
, System.arrayCopy
y Arrays.copyOf
tienen un rendimiento muy similar (jdk 1.7.06, servidor vm).
Para detalles (en ms), después de JIT:
clon: 68
arrayCopy: 68
Arrays.copyOf: 68
Código de prueba:
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];
}
En un esfuerzo por reducir la mutabilidad, deberíamos usar
public void setValues(String[] newVals) {
this.vals = ( newVals == null ? null : newVals.clone() );
}
o
public void setValues(String[] newVals) {
this.vals = ( newVals == null ? null : Arrays.copyOf(newVals, newVals.length) );
}
Considere también la seguridad de usar "clone ()". Una clase de ataques conocidos utiliza clases que anulan los métodos de "clonación" () de objetos con código malicioso. Por ejemplo, CVE-2012-0507 (el ataque "Flashback" en Mac OS) se solucionó básicamente reemplazando una llamada ".clone ()" con una llamada ".copyOf".
Se puede encontrar una discusión adicional sobre la obsolescencia de "clone ()" en aquí: clonación de objetos sin implementación de interfaz clonable
En términos de mutabilidad, proporcionarán exactamente la misma copia superficial de los datos.
Escribí un programa simple para verificar la diferencia.
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));
}
Y produce
[a, b, c]
[a, b, d]
[a, b, c]
[a, b, d]
Time Required for Clone: 26288
Time Required for Copy of: 25413
Entonces, si ves en ambos casos String[]
es inmutable y el rendimiento es casi el mismo pensamiento Arrays.copyOf () es un poco más rápido en mi máquina.
Actualizar
Cambié el programa para crear una matriz grande [100 cadenas] en lugar de una matriz pequeña.
String[] str = new String[100];
for(int i= 0; i<str.length;i++)
{
str[i]= Integer.toString(i);
}
Y movió la copy of
método antes copy of
método de clone
. Con los resultados a continuación.
Time Required for Copy of: 415095
Time Required for Clone: 428501
Que son más de lo mismo. Please do not ask me to run the test again as it takes a while
:(
Actualización 2
Para String array 1000000
y para número de iteraciones 10000
Time Required for Copy of: 32825
Time Required for Clone: 30138
copy of
toma más tiempo que clone