2010-11-21 23 views
11

¿Por qué aparece con diferentes comportamientos:Java addAll (colección) vs new ArrayList (colección)

  1. Collection col2 = new ArrayList(col);

  2. Collection col2 = new ArrayList();
    col2.addAll(col)

estoy trabajando con los espectadores, y el código es complejo, y estoy tratando de explicar la "raíz" del problema . Otro dato interesante es la siguiente ...

//IF i use this code i have the correct behavior in my app: 
public void updateCollection(Collection<Object> col) { 
    this.objectCollection.clear(); 
    this.objectCollection.addAll(col); 
} 

//IF i use this code i have unexpected behavior in my app: 
public void updateCollection(Collection<Object> col) { 
    this.objectCollection=new ArrayList(col); 
} 
+7

aclare, ¿qué comportamiento exacto le resulta confuso? –

+0

Mi código tiene comportamientos diferentes utilizando a) o b). En mi opinión, ambas operaciones conducirán al mismo resultado, pero aparentemente NO lo hacen. Algo es diferente – marcolopes

+2

Aún eres demasiado vago. ¿Lo que pasa? ¿Qué pasa no? Publique un [SSCCE] (http://sscce.org) junto con los resultados (no) esperados en su entorno. – BalusC

Respuesta

14

Este código funciona:

public void updateCollection(Collection<Object> col) { 
    this.objectCollection.clear(); 
    this.objectCollection.addAll(col); 
} 

Pero esto presenta problemas:

public void updateCollection(Collection<Object> col) { 
    this.objectCollection=new ArrayList(col); 
} 

Sospecho que esta variación en su primer método introduciría problemas idénticos:

public void updateCollection(Collection<Object> col) { 
    this.objectCollection = new ArrayList(); 
    this.objectCollection.clear(); 
    this.objectCollection.addAll(col); 
} 

¿Por qué? Evidentemente, tiene otra referencia a objectCollection en uso en alguna parte. En algún lugar de su código, otro objeto dice (por ejemplo):

myCopyOfObjectCollection = theOtherObject.objectCollection;

Si está utilizando un captador, que no cambia el comportamiento subyacente - que todavía está manteniendo otra referencia alrededor.

lo tanto, si en la asignación inicial, por ejemplo, la colección contenía {1, 2, 3}, se empieza con:

  • this.objectCollection: {1, 2, 3}
  • eso.copyOfObjectCollection: {1, 2, 3}

Cuando se asigna un nuevo ArrayList a this.objectCollection, y rellenarla con, por ejemplo, {4, 5, 6}, se obtiene lo siguiente:

  • this.objectCollection: {4, 5, 6}
  • that.copyOfObjectCollection: {1, 2, 3}

"que" todavía está apuntando a la ArrayList originales.

5
Collection col2 = new ArrayList(col); 

va a crear un nuevo ArrayList con el tamaño col.size() (+ 10%) y copiar todos los elementos de col en esa matriz.

Collection col2 = new ArrayList(); 

creará una nueva ArrayList con un tamaño inicial de 10 (al menos en la implementación de Sun).

col2.addAll(col); 

copiará todos los elementos de col en el extremo de la col2ArrayList, agrandando el tamaño de la matriz de soporte, si es necesario.

Así, dependiendo del tamaño de la colección col, el comportamiento será un poco diferente, pero no demasiado.

Es preferible utilizar la primera opción - que evite al menos una operación de respaldo expansión del array extra.

+0

Usando el primer acercamiento mi código no funciona ... – marcolopes

0
public List getAdminImIdsWithValidShortNames(){ 
    return adminImIdsWithValidShortNames; 
} 

public void setAdminImIdsWithValidShortNames(List adminImIdsWithValidShortNames){ 
    this.adminImIdsWithValidShortNames=adminImIdsWithValidShortNames; 
} 

Creo que, fácil es hermoso, solo el método de generador/conservera es un buen hábito. si borra primero, luego agregue Todos, la lista debe borrar todos los elementos de la lista, y luego agregar. Todo será una operación adicional de expansión de matriz de respaldo, eso no es ciencia.

solo reemplazo, esta variable apunta a la nueva lista, la lista anterior será auto-GC.

Cuestiones relacionadas