objetos mostrar lista les las funciona framework espaƱol elementos ejemplos conoce como colecciones java list collections copy

lista - mostrar elementos de un arraylist java



Lista de copias de colecciones de Java: no entiendo (18)

Tengo una ArrayList y quiero copiarla exactamente. Utilizo las clases de utilidad cuando es posible en el supuesto de que alguien pasó algún tiempo para hacerlo correcto. Así que, naturalmente, termino con la clase Collections que contiene un método de copia.

Supongamos que tengo lo siguiente:

List<String> a = new ArrayList<String>(); a.add("a"); a.add("b"); a.add("c"); List<String> b = new ArrayList<String>(a.size()); Collections.copy(b,a);

Esto falla porque, básicamente, cree que b no es lo suficientemente grande como para contener a . Sí, sé que b tiene el tamaño 0, pero debería ser lo suficientemente grande ahora, ¿no? Si tengo que llenar b primero, entonces Collections.copy() vuelve una función completamente inútil en mi mente. Entonces, excepto para programar una función de copia (¿qué voy a hacer ahora?), ¿Hay una forma adecuada de hacerlo?


¿Por qué no usas el método addAll ?

List a = new ArrayList(); a.add("1"); a.add("abc"); List b = b.addAll(listA); //b will be 1, abc

incluso si tiene elementos existentes en b o si desea poner algunos elementos después, como por ejemplo:

List a = new ArrayList(); a.add("1"); a.add("abc"); List b = new ArrayList(); b.add("x"); b.addAll(listA); b.add("Y"); //b will be x, 1, abc, Y


Como menciona hoijui. La respuesta seleccionada de Stephen Katulka contiene un comentario sobre Collections.copy que es incorrecto. El autor probablemente lo aceptó porque la primera línea de código estaba haciendo la copia que él quería. La llamada adicional a Collections.copy solo copia nuevamente. (Resultando en que la copia ocurra dos veces).

Aquí hay un código para probarlo.

public static void main(String[] args) { List<String> a = new ArrayList<String>(); a.add("a"); a.add("b"); a.add("c"); List<String> b = new ArrayList<String>(a); System.out.println("There should be no output after this line."); // Note, b is already a shallow copy of a; for (int i = 0; i < a.size(); i++) { if (a.get(i) != b.get(i)) { System.out.println("Oops, this was a deep copy."); // Note this is never called. } } // Now use Collections.copy and note that b is still just a shallow copy of a Collections.copy(b, a); for (int i = 0; i < a.size(); i++) { if (a.get(i) != b.get(i)) { System.out.println("Oops, i was wrong this was a deep copy"); // Note this is never called. } } // Now do a deep copy - requires you to explicitly copy each element for (int i = 0; i < a.size(); i++) { b.set(i, new String(a.get(i))); } // Now see that the elements are different in each for (int i = 0; i < a.size(); i++) { if (a.get(i) == b.get(i)) { System.out.println("oops, i was wrong, a shallow copy was done."); // note this is never called. } } }


Con Java 8 como nulo, podría usar el siguiente código.

List<String> b = Optional.ofNullable(a) .map(list -> (List<String>) new ArrayList<>(list)) .orElseGet(Collections::emptyList);

O usando un colector

List<String> b = Optional.ofNullable(a) .map(List::stream) .orElseGet(Stream::empty) .collect(Collectors.toList())


Copiar no es inútil si imagina el caso de uso para copiar algunos valores en una colección existente. Es decir, desea sobrescribir los elementos existentes en lugar de insertarlos.

Un ejemplo: a = [1,2,3,4,5] b = [2,2,2,2,3,3,3,3,3,4,4,4,] a.copy (b) = [1,2,3,4,5,3,3,3,3,4,4,4]

Sin embargo, esperaría un método de copia que tomaría parámetros adicionales para el índice de inicio de la colección de origen y destino, así como un parámetro para el recuento.

Ver Java BUG 6350752


Cualquier otro objeto no -> necesita repetir y hacer una copia usted mismo.

Para evitar este implemento clonable.

public class User implements Serializable, Cloneable { private static final long serialVersionUID = 1L; private String user; private String password; ... @Override public Object clone() { Object o = null; try { o = super.clone(); } catch(CloneNotSupportedException e) { } return o; } }

....

public static void main(String[] args) { List<User> userList1 = new ArrayList<User>(); User user1 = new User(); user1.setUser("User1"); user1.setPassword("pass1"); ... User user2 = new User(); user2.setUser("User2"); user2.setPassword("pass2"); ... userList1 .add(user1); userList1 .add(user2); List<User> userList2 = new ArrayList<User>(); for(User u: userList1){ u.add((User)u.clone()); } //With this you can avoid /* for(User u: userList1){ User tmp = new User(); tmp.setUser(u.getUser); tmp.setPassword(u.getPassword); ... u.add(tmp); } */ }


El siguiente resultado ilustra los resultados de usar copy constructor y Collections.copy ():

Copy [1, 2, 3] to [1, 2, 3] using copy constructor. Copy [1, 2, 3] to (smaller) [4, 5] java.lang.IndexOutOfBoundsException: Source does not fit in dest at java.util.Collections.copy(Collections.java:556) at com.farenda.java.CollectionsCopy.copySourceToSmallerDest(CollectionsCopy.java:36) at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:14) Copy [1, 2] to (same size) [3, 4] source: [1, 2] destination: [1, 2] Copy [1, 2] to (bigger) [3, 4, 5] source: [1, 2] destination: [1, 2, 5] Copy [1, 2] to (unmodifiable) [4, 5] java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableList.set(Collections.java:1311) at java.util.Collections.copy(Collections.java:561) at com.farenda.java.CollectionsCopy.copyToUnmodifiableDest(CollectionsCopy.java:68) at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:20)

La fuente del programa completo está aquí: copia de la lista de Java . Pero el resultado es suficiente para ver cómo se comporta java.util.Collections.copy ().


La mayoría de las respuestas aquí no se dan cuenta del problema, el usuario quiere tener una COPIA de los elementos de la primera lista a la segunda lista, los elementos de la lista de destinos son objetos nuevos y no hacen referencia a los elementos de la lista original. (significa que cambiar un elemento de la segunda lista no debe cambiar los valores del elemento correspondiente de la lista de origen.) Para los objetos mutables no podemos usar el constructor ArrayList (Colección) porque se referirá al elemento de la lista original y no se copiará. Necesita tener un clonador de lista para cada objeto al copiar.


La respuesta de Stephen Katulka (respuesta aceptada) es incorrecta (la segunda parte). Explica que Collections.copy(b, a); hace una copia profunda, que no lo hace. Ambos, new ArrayList(a); y Collections.copy(b, a); solo haz una copia superficial La diferencia es que el constructor asigna memoria nueva y la copy(...) no, lo que lo hace adecuado en casos en los que puede reutilizar matrices, ya que tiene una ventaja de rendimiento allí.

La API estándar de Java intenta desalentar el uso de copias profundas, ya que sería malo que los nuevos codificadores usen esto de forma regular, lo que también puede ser una de las razones por las cuales clone() no es público por defecto.

El código fuente de Collections.copy(...) se puede ver en la línea 552 en: http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/Collections-Jar-Zip-Logging-regex/java/util/Collections.java.htm

Si necesita una copia profunda, debe iterar sobre los elementos manualmente, utilizando un bucle for y clone () en cada objeto.


Las cadenas se pueden copiar profundamente con

List<String> b = new ArrayList<String>(a);

porque son inmutables. Cualquier otro objeto no -> necesita repetir y hacer una copia usted mismo.


Para comprender por qué Collections.copy () arroja una excepción IndexOutOfBoundsException aunque ha hecho que la matriz de respaldo de la lista de destinos sea lo suficientemente grande (mediante la llamada de size () en la lista de origen), consulte la respuesta de Abhay Yadav en esta pregunta relacionada: Cómo copia una java.util.List en otra java.util.List


Si quiere copiar una ArrayList, cópiela usando:

List b = new ArrayList(); b.add("aa"); b.add("bb"); List a = new ArrayList(b);


Solo haz:

List a = new ArrayList(); a.add("a"); a.add("b"); a.add("c"); List b = new ArrayList(a);

ArrayList tiene un constructor que aceptará otra Colección para copiar los elementos de


Vocación

List<String> b = new ArrayList<String>(a);

crea una copia superficial de a dentro de b . Todos los elementos existirán dentro de b en el mismo orden en el que estaban dentro de a (suponiendo que tuviera un orden).

Del mismo modo, llamando

// note: instantiating with a.size() gives `b` enough capacity to hold everything List<String> b = new ArrayList<String>(a.size()); Collections.copy(b, a);

también crea una copia superficial de a dentro de b . Si el primer parámetro, b , no tiene suficiente capacidad (no tamaño) para contener todos los elementos, entonces arrojará una IndexOutOfBoundsException . La expectativa es que Collections.copy no requerirá asignaciones para que funcionen, y si las hay, arrojará esa excepción. Es una optimización exigir que la colección copiada sea preasignada ( b ), pero generalmente no creo que la función valga la pena debido a las comprobaciones requeridas dadas las alternativas basadas en el constructor como la que se muestra arriba que no tienen efectos secundarios extraños.

Para crear una copia profunda, la List , a través de cualquiera de los mecanismos, debería tener un conocimiento complejo del tipo subyacente. En el caso de String s, que son inmutables en Java (y .NET para el caso), ni siquiera necesita una copia profunda. En el caso de MySpecialObject , necesita saber cómo hacer una copia profunda y no es una operación genérica.

Nota: La respuesta originalmente aceptada fue el resultado principal de Collections.copy en Google, y fue completamente incorrecta, como se señala en los comentarios.


Y si está usando google guava, la solución de una línea sería

List<String> b = Lists.newArrayList(a);

Esto crea una instancia de lista de matriz mutable.


la forma más sencilla de copiar una lista es pasarla al constructor de la nueva lista:

List<String> b = new ArrayList<>(a);

b será una copia superficial de

Mirando el origen de Collections.copy(List,List) (nunca lo había visto antes) parece ser para hacer frente a los elementos indexados por índice. usando List.set(int,E) así el elemento 0 sobre escribirá el elemento 0 en la lista de objetivos, etc. etc. No estoy particularmente claro de los javadocs que tendría que admitir.

List<String> a = new ArrayList<>(a); a.add("foo"); b.add("bar"); List<String> b = new ArrayList<>(a); // shallow copy ''a'' // the following will all hold assert a.get(0) == b.get(0); assert a.get(1) == b.get(1); assert a.equals(b); assert a != b; // ''a'' is not the same object as ''b''


b tiene una capacidad de 3, pero un tamaño de 0. El hecho de que ArrayList tenga algún tipo de capacidad de almacenamiento intermedio es un detalle de implementación; no es parte de la interfaz de la List , por lo que Collections.copy(List, List) no lo usa . Sería feo para el caso especial ArrayList .

Como MrWiggles ha indicado, usar el constructor ArrayList que toma una colección es la forma de hacerlo en el ejemplo provisto.

Para escenarios más complicados (que bien pueden incluir su código real), puede encontrar útil la biblioteca Google Java Collections .


List b = new ArrayList(a.size())

no establece el tamaño. Establece la capacidad inicial (es decir, cuántos elementos puede caber antes de que tenga que cambiar el tamaño). Una forma más simple de copiar en este caso es:

List b = new ArrayList(a);


private List<Item> cloneItemList(final List<Item> items) { Item[] itemArray = new Item[items.size()]; itemArray = items.toArray(itemArray); return Arrays.asList(itemArray); }