java - metodo - Hacer copia de la matriz
jlabel html (10)
Tengo una matriz que se actualiza constantemente. Digamos que a = [1,2,3,4,5]
. Necesito hacer una copia duplicada exacta de a
y llamarlo b
. Si a
se cambiara a [6,7,8,9,10], b
aún debería ser [1,2,3,4,5]. ¿Cuál es la mejor manera de hacer esto? Probé un bucle 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 copia profunda, etc. porque no sé lo que eso significa.
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 Object proporciona el método clone () y como array en java también es un Object, puede usar este método para lograr una copia de array completa. Este método no le convendrá si desea una copia parcial de la matriz.
System.arraycopy () : la clase del sistema arraycopy () es la mejor manera de hacer una copia parcial de una matriz. Le proporciona una manera fácil de especificar el número total de elementos para copiar y las posiciones de índice de matriz de origen y destino. Por ejemplo, System.arraycopy (source, 3, destination, 2, 5) copiará 5 elementos desde el origen hasta el destino, comenzando desde el tercer índice del origen hasta el segundo índice del destino.
Arrays.copyOf (): Si desea copiar los primeros elementos de una matriz o una copia completa de la matriz, puede utilizar este método. Obviamente, no es versátil como System.arraycopy () pero tampoco es confuso y fácil de usar.
Arrays.copyOfRange () : si desea copiar algunos elementos de una matriz, donde el índice de inicio no es 0, puede usar este método para copiar una matriz parcial.
Para una copia segura de nulos de una matriz, también puede usar un método opcional con el método Object.clone()
que se proporciona en esta answer .
int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
Puedes 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 intentar usar Arrays.copyOf () en Java
int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
Si debe trabajar con matrices en bruto y no con ArrayList
entonces 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 cantidad de programación defensiva porque el método System.arraycopy()
lanza muchas excepciones sin System.arraycopy()
si lo alimenta con parámetros ilógicos.
Puede usar Arrays.copyOf()
que se copiará desde el primer elemento al Nth
al nuevo array más corto.
public static <T> 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. Tales í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,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> 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> 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 original [de] se coloca en el elemento inicial de la copia (a menos que == original.length o de == a). Los valores de los elementos posteriores de la matriz original se colocan en los elementos posteriores de la copia. El índice final del rango (a), que debe ser mayor o igual que desde, puede ser mayor que original.length, en cuyo caso se coloca nulo 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á de - desde. La matriz resultante es exactamente de la misma clase que la matriz original.
3035 public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> 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, ambas son simplemente funciones de envoltura sobre System.arraycopy
con lógica defensiva que lo que intenta hacer es válido.
System.arraycopy
es la forma más rápida de copiar arrays.
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 arreglos pequeños. Ambos elementos de copia son igualmente rápidos pero clone () devuelve Object
por lo que el compilador debe insertar una conversión implícita a int[]
. Puedes verlo en el bytecode, algo como esto:
ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
También puede utilizar 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 utilizan System.arraycopy
debajo del capó.
Ver
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 bucle for como [...] pero ¿parece que no funciona correctamente?
Mirando ese bucle, no hay ninguna razón obvia para que no funcione ... a menos que:
- de alguna manera, los arreglos a y
b
mal estado (por ejemplo,a
yb
refieren al mismo arreglo), o - su aplicación es multihebra y diferentes hebras leen y actualizan
a
matriz simultáneamente.
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 alguna 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 la sincronización con un mutex primitivo hará el truco.
(Hay indicios en su pregunta que me llevan a pensar que esto está relacionado con el hilo; por ejemplo, su afirmación de que a
está cambiando constantemente).
Toda la solución que llame a la longitud desde la matriz, agregue su código redundante.
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();
}
}
Le recomiendo que no invente la rueda y use la clase de utilidad donde ya se han realizado todas las comprobaciones necesarias. Considere 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 there
puedes usar
int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();
también.