Hacer copia de matriz

Tengo una matriz que se actualiza constantemente. Digamos a = [1,2,3,4,5] . Necesito hacer una copia exacta de a y llamarla b . Si a cambiara a [6,7,8,9,10], b todavía debería ser [1,2,3,4,5]. ¿Cuál es la mejor manera de hacer esto? Intenté un ciclo for como:

 for(int i=0; i<5; i++){ b[i]=a[i] } 

pero eso no parece funcionar correctamente. Por favor, no use términos avanzados como “deep copy”, etc. porque no sé lo que eso significa.

Puede intentar usar System.arraycopy ()

 int[] src = new int[]{1,2,3,4,5}; int[] dest = new int[5]; System.arraycopy( src, 0, dest, 0, src.length ); 

puedes usar

 int[] a = new int[]{1,2,3,4,5}; int[] b = a.clone(); 

también.

Si quieres hacer una copia de:

 int[] a = {1,2,3,4,5}; 

Este es el camino a seguir:

 int[] b = Arrays.copyOf(a, a.length); 

Arrays.copyOf puede ser más rápido que a.clone() en matrices pequeñas. Ambos elementos de copia son igualmente rápidos pero clone () devuelve Object por lo que el comstackdor tiene que insertar un molde implícito en int[] . Puedes verlo en el bytecode, algo como esto:

 ALOAD 1 INVOKEVIRTUAL [I.clone ()Ljava/lang/Object; CHECKCAST [I ASTORE 2 

Buena explicación de http://www.journaldev.com/753/how-to-copy-arrays-in-java

Métodos de copia de matriz de Java

Object.clone () : la clase de objeto proporciona el método clone () y dado que array en java también es un objeto, puede usar este método para lograr una copia de matriz completa. Este método no le conviene si quiere una copia parcial de la matriz.

System.arraycopy () : System Class arraycopy () es la mejor forma de hacer una copia parcial de una matriz. Le proporciona una manera fácil de especificar la cantidad total de elementos para copiar y las posiciones del índice de matriz de origen y destino. Por ejemplo, System.arraycopy (fuente, 3, destino, 2, 5) copiará 5 elementos desde el origen hasta el destino, comenzando desde el tercer índice de origen hasta el segundo índice de destino.

Arrays.copyOf (): si desea copiar los primeros elementos de una matriz o una copia completa de la matriz, puede usar este método. Obviamente no es tan versátil como System.arraycopy () pero tampoco es confuso y fácil de usar.

Arrays.copyOfRange () : si desea copiar pocos elementos de una matriz, donde el índice inicial no es 0, puede utilizar este método para copiar una matriz parcial.

Tengo la sensación de que todas estas “mejores formas de copiar una matriz” realmente no van a resolver su problema.

Tu dices

Intenté un ciclo for como […] pero eso no parece funcionar correctamente?

Al observar ese ciclo, no hay una razón obvia para que no funcione … a menos que:

  • de alguna manera tienes las matrices a y b mal (por ejemplo, a y b refieren a la misma matriz), o
  • tu aplicación tiene varios subprocesos y diferentes subprocesos están leyendo y actualizando a conjunto de forma simultánea.

En cualquier caso, las formas alternativas de hacer la copia no resolverán el problema subyacente.

La solución para el primer escenario es obvia. Para el segundo escenario, tendrás que encontrar la forma de sincronizar los hilos. Las clases de matriz atómica no ayudan porque no tienen constructores de copia atómica o métodos de clonación, pero sincronizar usando un mutex primitivo hará el truco.

(Hay sugerencias en su pregunta que me llevan a pensar que esto está de hecho relacionado con el hilo, por ejemplo, su afirmación de que a cambia constantemente).

Todas las soluciones que llaman longitudes desde array, agregan su código inspecciones nulas redundantesconsiderado ejemplo:

 int[] a = {1,2,3,4,5}; int[] b = Arrays.copyOf(a, a.length); int[] c = a.clone(); //What if array a comes as local parameter? You need to use null check: public void someMethod(int[] a) { if (a!=null) { int[] b = Arrays.copyOf(a, a.length); int[] c = a.clone(); } } 

Recomiendo que no invente la rueda y use la clase de utilidad donde ya se han realizado todas las comprobaciones necesarias. Considera ArrayUtils de apache commons. Tu código se vuelve más corto:

 public void someMethod(int[] a) { int[] b = ArrayUtils.clone(a); } 

Apache comunes que puedes encontrar allí

También puede usar Arrays.copyOfRange .

Ejemplo :

 public static void main(String[] args) { int[] a = {1,2,3}; int[] b = Arrays.copyOfRange(a, 0, a.length); a[0] = 5; System.out.println(Arrays.toString(a)); // [5,2,3] System.out.println(Arrays.toString(b)); // [1,2,3] } 

Este método es similar a Arrays.copyOf , pero es más flexible. Ambos usan System.arraycopy debajo del capó.

Ver :

Puede intentar usar Arrays.copyOf () en Java

 int[] a = new int[5]{1,2,3,4,5}; int[] b = Arrays.copyOf(a, a.length); 

Para una copia nula segura de una matriz, también puede usar una opción con el método Object.clone() provisto en esta respuesta .

 int[] arrayToCopy = {1, 2, 3}; int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null); 

Si debe trabajar con matrices en bruto y no con ArrayList , Arrays tiene lo que necesita. Si observa el código fuente, estas son las mejores formas de obtener una copia de una matriz. Tienen una buena parte de la progtwigción defensiva porque el método System.arraycopy() arroja muchas excepciones no verificadas si le das parámetros ilógicos.

Puede usar cualquiera de los Arrays.copyOf() que copiará del primer al Nth elemento a la nueva matriz más corta.

 public static  T[] copyOf(T[] original, int newLength) 

Copia la matriz especificada, truncando o rellenando con nulos (si es necesario) para que la copia tenga la longitud especificada. Para todos los índices que son válidos tanto en la matriz original como en la copia, las dos matrices contendrán valores idénticos. Para cualquier índice que sea válido en la copia pero no en el original, la copia contendrá nulo. Dichos índices existirán si y solo si la longitud especificada es mayor que la de la matriz original. La matriz resultante es exactamente de la misma clase que la matriz original.

 2770 2771 public static  T[] More ...copyOf(U[] original, int newLength, Class newType) { 2772 T[] copy = ((Object)newType == (Object)Object[].class) 2773 ? (T[]) new Object[newLength] 2774 : (T[]) Array.newInstance(newType.getComponentType(), newLength); 2775 System.arraycopy(original, 0, copy, 0, 2776 Math.min(original.length, newLength)); 2777 return copy; 2778 } 

o Arrays.copyOfRange() también hará el truco:

 public static  T[] copyOfRange(T[] original, int from, int to) 

Copia el rango especificado de la matriz especificada en una nueva matriz. El índice inicial del rango (desde) debe estar entre cero y original.length, inclusive. El valor en el original [de] se coloca en el elemento inicial de la copia (a menos que sea de == original.length o de == a). Los valores de los elementos subsiguientes en la matriz original se colocan en los elementos subsiguientes en la copia. El índice final del rango (to), que debe ser mayor o igual que from, puede ser mayor que original.length, en cuyo caso null se coloca en todos los elementos de la copia cuyo índice es mayor o igual que el original. longitud – desde. La longitud de la matriz devuelta será – desde. La matriz resultante es exactamente de la misma clase que la matriz original.

 3035 public static  T[] More ...copyOfRange(U[] original, int from, int to, Class newType) { 3036 int newLength = to - from; 3037 if (newLength < 0) 3038 throw new IllegalArgumentException(from + " > " + to); 3039 T[] copy = ((Object)newType == (Object)Object[].class) 3040 ? (T[]) new Object[newLength] 3041 : (T[]) Array.newInstance(newType.getComponentType(), newLength); 3042 System.arraycopy(original, from, copy, 0, 3043 Math.min(original.length - from, newLength)); 3044 return copy; 3045 } 

Como puede ver, ambos son solo funciones de contenedor sobre System.arraycopy con una lógica defensiva de que lo que está tratando de hacer es válido.

System.arraycopy es la forma más rápida de copiar matrices.