Подтвердить что ты не робот

Java addAll (коллекция) vs new ArrayList (коллекция)

Почему у меня разные поведения:

  • Collection col2 = new ArrayList(col);

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

Я работаю с зрителями, и код сложный, и я пытаюсь объяснить "корень" проблемы. Еще один интересный факт - следующий...

//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);
}
4b9b3361

Ответ 1

Этот код работает:

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

Но это вводит проблемы:

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

Я подозреваю, что эта вариация вашего первого метода приведет к идентичным проблемам:

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

Почему? Очевидно, у вас есть другая ссылка на objectCollection, где-то используется. Где-то в вашем коде другой объект говорит (например):

myCopyOfObjectCollection = theOtherObject.objectCollection;

Если вы используете getter, это не изменяет базовое поведение - вы все еще сохраняете другую ссылку.

Итак, если при первоначальном назначении, скажем, в коллекции, содержащей {1, 2, 3}, вы начинаете с:

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

Когда вы назначаете новый ArrayList этому .objectCollection и заполняете его, скажем, {4, 5, 6}, вы получаете следующее:

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

", который" все еще указывает на исходный ArrayList.

Ответ 2

Collection col2 = new ArrayList(col);

создаст новый ArrayList с размером col.size() (+ 10%) и скопирует все элементы из col в этот массив.

Collection col2 = new ArrayList();

создаст новый ArrayList с начальным размером 10 (по крайней мере, в реализации Sun).

col2.addAll(col);

скопирует все элементы из col в конец col2 ArrayList, при необходимости увеличив размер массива поддержки.

Итак, в зависимости от вашего размера коллекции col поведение будет немного иным, но не слишком большим.

Предпочтительно использовать первый вариант - это позволит избежать по крайней мере одной дополнительной операции расширения массива.

Ответ 3

    public List getAdminImIdsWithValidShortNames(){
    return adminImIdsWithValidShortNames;
}

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

Я думаю, легко красиво, просто метод генератора/геттера - хорошая привычка. если вы сначала очистите, а затем addAll, список должен очистить все элементы списка, а затем addAll будет дополнительной операцией расширения массива, что не наука.

просто замена, эта переменная будет указывать на новый список, старый список будет автоматически GC.