Quiero crear una nueva matriz de objetos juntando dos matrices más pequeñas.
No pueden ser nulos, pero el tamaño puede ser 0.
No puedo elegir entre estas dos formas: ¿son equivalentes o una más eficiente (por ejemplo, system.arraycopy () copia fragmentos completos)?
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
System.arraycopy(publicThings, 0, things, 0, publicThings.length);
System.arraycopy(privateThings, 0, things, publicThings.length, privateThings.length);
o
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
for (int i = 0; i < things.length; i++) {
if (i<publicThings.length){
things[i] = publicThings[i]
} else {
things[i] = privateThings[i-publicThings.length]
}
}
¿La única diferencia es el aspecto del código?
EDITAR: gracias por la pregunta vinculada, pero parecen tener una discusión sin resolver:
¿Es realmente más rápido si it is not for native types
: byte [], Object [], char []? en todos los demás casos, se ejecuta una verificación de tipo, que sería mi caso y entonces sería equivalente ... ¿no?
En otra pregunta vinculada, dicen que the size matters a lot
, para un tamaño> 24, system.arraycopy () gana, para un tamaño menor que 10, el bucle manual es mejor ...
Ahora estoy realmente confundido.
arraycopy()
es una llamada nativa, que sin duda es más rápida.Respuestas:
Sé que las pruebas JUnit no son realmente las mejores para la evaluación comparativa, pero
testHardCopyBytes tardó 0.157s en completarse
y
testArrayCopyBytes tardó 0.086s en completarse.
Creo que depende de la máquina virtual, pero parece que copia bloques de memoria en lugar de copiar elementos de una sola matriz. Esto aumentaría absolutamente el rendimiento.
EDITAR:
Parece que el rendimiento de System.arraycopy está por todos lados. Cuando se usan cadenas en lugar de bytes y las matrices son pequeñas (tamaño 10), obtengo estos resultados:
Así es como se ve cuando las matrices tienen un tamaño de 0x1000000. Parece que System.arraycopy definitivamente gana con matrices más grandes.
¡Qué peculiar!
Gracias, Daren, por señalar que las referencias se copian de manera diferente. ¡Hizo de esto un problema mucho más interesante!
fuente
Arrays.copyOf(T[], int)
es más fácil de leer. Internamente usaSystem.arraycopy()
que es una llamada nativa.¡No puedes conseguirlo más rápido!
fuente
copyOf
no siempre se puede reemplazararraycopy
, pero es apropiado para este caso de uso.Depende de la máquina virtual, pero System.arraycopy debería brindarle lo más cercano que pueda al rendimiento nativo.
He trabajado durante 2 años como desarrollador de Java para sistemas integrados (donde el rendimiento es una gran prioridad) y en todos los lugares donde se podría usar System.arraycopy, lo he usado principalmente / lo he visto usado en código existente. Siempre se prefiere a los bucles cuando el rendimiento es un problema. Sin embargo, si el rendimiento no es un gran problema, seguiría el ciclo. Mucho más fácil de leer.
fuente
Arrays.copy
no existe,Arrays.copyOf
es una función de biblioteca.En lugar de confiar en la especulación y la información posiblemente desactualizada, ejecuté algunos puntos de referencia utilizando calibrar. De hecho, Caliper viene con algunos ejemplos, ¡incluido un
CopyArrayBenchmark
que mide exactamente esta pregunta! Todo lo que tienes que hacer es correrMis resultados se basan en Java HotSpot (TM) 64-Bit Server VM, 1.8.0_31-b13, que se ejecuta en una MacBook Pro de mediados de 2010 (macOS 10.11.6 con Intel Arrandale i7, 8 GiB de RAM). No creo que sea útil publicar los datos de tiempo sin procesar. Más bien, resumiré las conclusiones con las visualizaciones de apoyo.
En resumen:
for
bucle manual para copiar cada elemento en una matriz recién instanciada nunca es ventajoso, ya sea para matrices cortas o largas.Arrays.copyOf(array, array.length)
yarray.clone()
ambos son consistentemente rápidos. Estas dos técnicas tienen un rendimiento casi idéntico; cuál elijas es cuestión de gustos.System.arraycopy(src, 0, dest, 0, src.length)
es casi tan rápido como y , pero no tan consistentemente. (Vea el caso de 50000 s.) Por eso, y la verbosidad de la llamada, recomendaría si necesita un control preciso sobre qué elementos se copian y dónde.Arrays.copyOf(array, array.length)
array.clone()
int
System.arraycopy()
Aquí están las gráficas de tiempo:
fuente
La ejecución de métodos nativos como
Arrays.copyOf(T[], int)
tiene algunos gastos generales, pero no significa que no sea rápido, ya que lo está ejecutando utilizando JNI.La forma más sencilla es escribir un punto de referencia y realizar una prueba.
Puede comprobar que
Arrays.copyOf(T[], int)
es más rápido que sufor
ciclo normal .El código de referencia de aquí : -
System.arraycopy()
usa JNI (Java Native Interface) para copiar una matriz (o partes de ella), por lo que es increíblemente rápido, como puede confirmar aquífuente
System.arraycopy
no lo usa.System.arraycopy
no usa JNI, que es solo para llamar a bibliotecas de terceros. En cambio, es una llamada nativa, lo que significa que hay una implementación nativa en la VM para ella.No es posible que
Arrays.copyOf
sea más rápidoSystem.arraycopy
ya que esta es la implementación decopyOf
:fuente
System.arraycopy()
es una llamada nativa que copia la operación directamente en la memoria. La copia de memoria única siempre será más rápida que su bucle forfuente