2010-11-21 24 views
11

Dlaczego dostaję różne zachowania z:Java AddAll (kolekcja) vs new ArrayList (kolekcji)

  1. Collection col2 = new ArrayList(col);

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

pracuję z widzami, a kod jest złożony i próbuję wyjaśnić "root" problemu . Innym ciekawym faktem jest następny ...

//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

proszę wyjaśnić, które dokładne zachowanie jest dla Ciebie mylące? –

+0

Mój kod ma różne zachowania za pomocą a) lub b). Moim zdaniem obie operacje doprowadzą do tego samego wyniku, ale najwyraźniej NIE. Coś jest inne. – marcolopes

+2

Nadal jesteś zbyt nieokreślony. Co się dzieje? Co się nie dzieje? Proszę zamieścić [SSCCE] (http://sscce.org) wraz z (nie) oczekiwanymi wynikami w twoim środowisku. – BalusC

Odpowiedz

14

Ten kod działa:

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

Ale ta wprowadza problemy:

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

Podejrzewam, że to wariacja na temat swojej pierwszej metody wprowadzi identyczne problemy:

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

Dlaczego? Widocznie masz inne odniesienie do ObjectCollection w użyciu gdzieś. Gdzieś w kodzie, inny obiekt mówi (na przykład):

myCopyOfObjectCollection = theOtherObject.objectCollection;

Jeśli używasz gettera, to nie zmienia podstawowego zachowania - nadal zachowujesz inne odniesienie.

Więc jeśli na początkowym zadania, powiedzmy, kolekcja zawierała {1, 2, 3}, zaczynasz się z:

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

Po przypisaniu nowy ArrayList do this.objectCollection i wypełnić go z, powiedzmy, {4, 5, 6}, to masz:

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

"że" nadal wskazuje pierwotnego ArrayList.

5
Collection col2 = new ArrayList(col); 

stworzy nowy ArrayList o rozmiarze col.size() (+ 10%) i skopiować wszystkie elementy z col do tej tablicy.

Collection col2 = new ArrayList(); 

utworzy nową ArrayList z początkowym rozmiarem 10 (przynajmniej w implementacji Sun).

col2.addAll(col); 

skopiuje wszystkie elementy z col do końca col2ArrayList, powiększając rozmiar tablicy podkład, jeśli to konieczne.

Tak więc, w zależności od rozmiaru kolekcji col, zachowanie będzie nieco inne, ale niezbyt duże.

Zaleca się użycie pierwszej opcji - która pozwoli uniknąć co najmniej jednej dodatkowej operacji rozszerzenia tablicy.

+0

Korzystanie z pierwszego podejścia mój kod nie działa ... – marcolopes

0
public List getAdminImIdsWithValidShortNames(){ 
    return adminImIdsWithValidShortNames; 
} 

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

Myślę, że łatwe jest piękne, po prostu metoda generatora/gettera jest dobrym nawykiem. jeśli najpierw wyczyścisz, a następnie dodasz, lista będzie musiała wyczyścić wszystkie elementy listy, a następnie addAll będzie dodatkowym działaniem rozszerzenia tablicy, to nie jest nauka.

Po prostu zamiennik, ta zmienna będzie wskazywała na nową listę, stara lista będzie automatycznie-GC.