La toArray método en ArrayList, Bloch utiliza tanto System.arraycopy y Arrays.copyOf para copiar un array.

public <T> T[] toArray(T[] a) {
    if (a.length < size)
        //Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

¿Cómo puedo comparar estos dos métodos de copia y cuando debo usar que?

  • ¿Qué es «Bloch»? ¿Por qué es el fragmento de código relevantes?
  • Bloch es el hombre que escribió el ArrayList aplicación.
  • Véase también: stackoverflow.com/q/44487304/14955
InformationsquelleAutor Sawyer | 2010-04-07

9 Comentarios

  1. 98

    La diferencia es que Arrays.copyOf no sólo copia los elementos, también se crea una nueva matriz. System.arraycopy copias en una matriz existente.

    Aquí está el origen de Arrays.copyOf, como se puede ver se utiliza System.arraycopy internamente para llenar la nueva matriz:

    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
    • Su evidente….Las matrices.copia debe crear una nueva instancia de la matriz, ya que no estamos pasando uno a ella; mientras que pasan a un destino para el Sistema.arraycopy. En cuanto a la velocidad, de nuevo, obviamente, del Sistema.arraycopy debe ganar ya que es un método nativo y en última instancia de las Matrices.copia también se llama a este método para copiar una matriz.
    • El código fuente Java doesn no importa a partir de la intrínseca fue creado.
    • también System.arraycopy tiene más detallada de los parámetros, puede especificar el índice inicial de ambas matrices.
  2. 34

    Mientras System.arraycopy es implementado de forma nativa, y por lo tanto podría ser1 más rápido que Java bucle, no siempre es tan rápido como se podría esperar. Considere este ejemplo:

    Object[] foo = new Object[]{...};
    String[] bar = new String[foo.length];
    
    System.arraycopy(foo, 0, bar, 0, bar.length);

    En este caso, el foo y bar matrices tienen diferentes tipos de base, por lo que la implementación de arraycopy tiene para comprobar el tipo de cada referencia copiado para asegurarse de que es en realidad una referencia a una instancia de String. Que es significativamente más lento que un simple estilo C memcopy del contenido de la matriz.

    El otro punto es que Arrays.copyOf utiliza System.arraycopy bajo el capó. Por lo tanto System.arraycopy es en la cara de ella no debe ser más lento2 de Arrays.copyOf. Pero se puede ver (a partir del código citado por encima de) que Arrays.copyOf en algunos casos el uso de la reflexión para crear la nueva matriz. Para la comparación de rendimiento no es sencillo.

    Hay un par de fallos en este análisis.

    1. Estamos buscando en el código de la implementación de una versión específica de Java. Estos métodos pueden cambiar, lo que invalida los supuestos anteriores, acerca de la eficiencia.

    2. Estamos ignorando la posibilidad de que el compilador JIT de hacer algo inteligente caso especial de la optimización de estos métodos. Y al parecer esto sucede con Arrays.copyOf; ver ¿Por qué las Matrices.copia de 2 veces más rápida que la del Sistema.arraycopy para arreglos pequeños?. Este método es «intrínseca» en la actual generación de implementaciones de Java, lo que significa que el compilador JIT se ignoran lo que está en el código fuente de Java!

    Pero de cualquier manera, el diferencia entre las dos versiones es O(1) (es decir, independientes del tamaño de la matriz) y relativamente pequeño. Por lo tanto, mi consejo sería utilizar la versión que hace el código más fácil de leer, y sólo preocuparse de que uno es más rápido si perfiles le dice que es importante.


    1 – Se podría ser más rápido, pero es también posible que el compilador JIT hace un buen trabajo de optimización de una mano el código del bucle que no hay ninguna diferencia.

    • +1 para señalar el tipo de comprobación que tiene que ocurrir a veces.
    • Respecto a tu primer párrafo, hay casos donde System.arrayCopy en realidad podría ser más lento?
    • No soy consciente de ninguna. Pero no es imposible.
    • Un poco tarde en esta respuesta, pero teniendo en cuenta que el Sistema.arrayCopy se hace referencia por las Matrices.copia (Como se menciona en la respuesta) yo tendría que aruge que es imposible para el Sistema.arrayCopy a ser más lento. Esta condición, por supuesto, que no es una costumbre de la implementación de la JVM con una implementación personalizada de los métodos.
    • Usted está haciendo suposiciones acerca de las optimizaciones que el compilador JIT hace. Es posible que ignora completamente el código fuente / bytecode que usted está buscando. O que podría hacer que en alguna futura versión de Java. O que el código fuente puede ser diferente en alguna otra versión. O que hay algún inteligente de optimización que se puede hacer en un directo arraycopy llamada que no puede ser hecho en una llamada indirecta. Todas estas cosas son posibles … si no plausible.
  3. 13

    Si quieres un exacta copia de una matriz (por ejemplo, si usted quiere hacer una defensiva copia), la forma más eficaz de la copia de un array es, probablemente, el uso de la matriz del objeto clone() método:

    class C {
        private int[] arr;
        public C(int[] values){
            this.arr = values.clone();
        }
    }

    No he molestado en probar el rendimiento de la misma, pero encuentra una buena oportunidad para ser muy rápido ya que todos los nativos (asignación y copia en la llamada), y la clonación es un tipo de especial de la JVM bendita manera de copiar los objetos (y principalmente el mal para otros fines) y es probable que sea capaz de tomar algunos «atajos».

    Personalmente, yo todavía uso clone si era más lento que cualquier otra forma de copiar, porque es más fácil de leer y casi imposible de meter la pata al escribir. System.arrayCopy, en el otro lado…

    • A la derecha, pero System.arrayCopy es nativo así (y es dedicado a esa tarea), mientras que clone parecen tener que lidiar con muchos condiciones
    • no suelen utilizar clone… pero cuando lo hago, yo lo uso en matrices».
    • Yo estaba hablando acerca de que .clone() cuando se utiliza en matrices…. En cualquier caso, todavía devuelve un Objeto que luego debe ser vaciada en un array (= trabajo adicional).
    • en realidad es sobrecargado con el correcto tipo de retorno para todos los tipos de matriz, de modo que usted no tiene que hacer cualquier casting a sí mismo, y no es cierto que la VM se tiene que comprobar cualquier arroja.
    • Buen punto, por lo que usted está diciendo que el nativo clone() será más rápido que los nativos System.arrayCopy porque clone() se dedica a esta tarea así?
    • Bueno, ya clone es más especializado que System.arrayCopy, hay más habitaciones para la optimización (por ejemplo, usted no necesita hacer cualquier comprobación de límites). Esto no es lo mismo que decir que se ser más rápido (por ejemplo, S.aC es el más ampliamente utilizado y por lo tanto hay más incentivos para que la máquina virtual de escritores de mejorarlo).
    • Anywho, la razón para el uso de la clonación no es de velocidad, sino de sencillez que usted no tiene que recordar el orden de los parámetros de S.aC, y no habrá off-by-one errores, etc. Como para el rendimiento, la diferencia está obligado a ser insignificante, o tal vez incluso no se puede medir, por tan buena como la de todas las aplicaciones (y cuando no, tal vez usted no debe copiar un array en todos?).
    • La simplicidad puede ser una ventaja añadida, pero la pregunta en la parte superior es preguntar específicamente sobre el rendimiento, lo que significa que estas funciones se encuentra en algún lugar profundo dentro de una biblioteca de empleo de fachada patrón, por lo tanto, es igual de «fácil de usar».

  4. 12

    Sistema.arrayCopy es mucho más rápido. Es en el sistema debido a que utiliza un directo de la copia de la memoria fuera de Java de la tierra. Lo uso cuando sea posible.

    • Pero El Sistema.arraycopy sólo copias en una matriz existente. Las matrices.copia también se crea la matriz de salida para usted.
    • Eso es cierto, y siempre y cuando usted está utilizando el Sistema.arraycopy bajo el cubre cualquier conveniencia de contenedor que se utilice es sólo la salsa.
    • Y, hay casos donde System.arrayCopy no el uso directo de la copia de la memoria.
  5. 11

    Has mirado en el Sol de la implementación de los Arrays.copia()?

     public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    Como se puede ver, utiliza System.arraycopy() internamente, por lo que el rendimiento sería el mismo.

  6. 2

    En lugar de debatir, estos son los resultados reales. Claramente, su elección dependerá de la cantidad de datos que desea copiar.

    byte[] copia de la prueba de rendimiento

    10.000.000 de iteraciones 40b
    de la matriz.copyOfRange: 135ms
    sistemas.arraycopy: 141ms

    10.000.000 de iteraciones 1000b
    de la matriz.copyOfRange: 1861ms
    sistemas.arraycopy: 2211ms

    10.000.000 de iteraciones 4000b
    de la matriz.copyOfRange: 6315ms
    sistemas.arraycopy: 5251ms

    1.000.000 de iteraciones 100.000 b
    de la matriz.copyOfRange: 15,198 ms
    sistemas.arraycopy: 14783ms

    • No sé por qué la downvote, este fue relevante y útil para la discusión.
  7. 1

    Si miramos el código fuente del Sistema.arraycopy() y de la Matriz.copia(), para el rendimiento.

    Sistema.arraycopy() es el código C, que opera directamente en la matriz, no devuelve ningún valor, y debido a que debe funcionar mucho más rápido que el de la Matriz.copia(). Sin embargo, si usted necesita una nueva matriz a la que se creó o si simplemente necesita el valor de la operación de copia, a continuación, usted tiene que crear una nueva matriz para que, de conjunto de la nueva matriz de longitud, etc… por Lo tanto, no se puede hacer un Sistema de retorno.arraycopy(de la fuente, 0, destino, 0, longitud).

    Por lo que la Matriz.copia() puede hacer a continuación, hacer una nueva matriz para usted. Usted puede asignar el valor de retorno de la Matriz.copia de() a una matriz o devolución de un método como el de la Matriz.copia() devolverá un valor en lugar de operar directamente sobre la matriz de destino. Por lo tanto, el código tendrá un aspecto mucho más limpio. Sin embargo, el costo de rendimiento, de la Matriz.copia() es un tipo genérico método y no saber de antemano lo que se va a trabajar. Por lo tanto, tiene que llamar a la Matriz.newInstance() o new Object() y, a continuación, fundido a la entrada del tipo de matriz.

    Así que para resumir. El Uso Del Sistema.arraycopy() porque de rendimiento. El Uso De La Matriz.copia() para un código más limpio.

  8. 0
          class ArrayCopyDemo {
       public static void main(String[] args) {
        char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
                'i', 'n', 'a', 't', 'e', 'd' };
        char[] copyTo = new char[7];
    
        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        System.out.println(new String(copyTo));
    }
     }

Dejar respuesta

Please enter your comment!
Please enter your name here