Java addAll(collection) vs new ArrayList(collection)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4238654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 05:27:33  来源:igfitidea点击:

Java addAll(collection) vs new ArrayList(collection)

javacollectionsarraylist

提问by marcolopes

Why do i get different behaviors with:

为什么我会出现不同的行为:

  1. Collection col2 = new ArrayList(col);

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

  1. Collection col2 = new ArrayList(col);

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

I'm working with viewers, and the code is complex, and i'm trying to explain the "root" of the problem. Another interesting fact is the next one...

我正在与观众一起工作,代码很复杂,我试图解释问题的“根源”。另一个有趣的事实是下一个......

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

回答by Carl Manaster

This code works:

此代码有效:

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

But this introduces problems:

但这会带来问题:

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

I suspect that this variation on your first method would introduce identical problems:

我怀疑您的第一种方法的这种变化会引入相同的问题:

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

Why? Evidently you have another reference to objectCollection in use somewhere. Somewhere in your code, another object is saying (for instance):

为什么?显然,您在某处使用了另一个对 objectCollection 的引用。在您的代码中,另一个对象说(例如):

myCopyOfObjectCollection = theOtherObject.objectCollection;

myCopyOfObjectCollection = theOtherObject.objectCollection;

If you're using a getter, that doesn't change the underlying behavior - you are still keeping another reference around.

如果您使用的是 getter,那不会改变底层行为 - 您仍然保留另一个引用。

So if on initial assignment, say, the collection contained {1, 2, 3}, you start out with:

因此,如果在初始分配中,例如,集合包含 {1, 2, 3},您可以从以下内容开始:

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

When you assign a newArrayList to this.objectCollection, and populate it with, say, {4, 5, 6}, you get this:

当您将新的ArrayList分配给 this.objectCollection,并使用 {4, 5, 6} 填充它时,您会得到:

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

"that" is still pointing to the original ArrayList.

“那个”仍然指向原始的 ArrayList。

回答by Neeme Praks

Collection col2 = new ArrayList(col);

will create a new ArrayListwith size col.size()(+10%) and copy all elements from colinto that array.

将创建一个ArrayList大小为col.size()(+10%)的新元素并将所有元素复制col到该数组中。

Collection col2 = new ArrayList();

will create a new ArrayList with initial size of 10 (at least in Sun implementation).

将创建一个初始大小为 10 的新 ArrayList(至少在 Sun 实现中)。

col2.addAll(col);

will copy all elements from colinto the end of the col2ArrayList, enlarging the backing array size, if needed.

如果需要,将把所有元素复制col到 的末尾col2ArrayList,扩大后备数组的大小。

So, depending on your colcollection size, the behavior will be a bit different, but not too much.

因此,根据您的col集合大小,行为会有所不同,但不会太大。

It is preferable to use the first option- that will avoid at least one extra backing array expansion operation.

最好使用第一个选项- 这将避免至少一个额外的支持数组扩展操作。

回答by zg_spring

    public List getAdminImIdsWithValidShortNames(){
    return adminImIdsWithValidShortNames;
}

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

I think, easy is beautiful, just generator setter/getter method is a good habit. if you first clear, then addAll, the list need to clear all elements of list, then addAll will be extra backing array expansion operation, that's not science.

我认为,简单就是美丽,只是生成器 setter/getter 方法是一个好习惯。如果先clear,然后addAll,list需要清空list的所有元素,那么addAll会是额外的backing数组扩展操作,这不科学。

just replacement, this variable will be point to new List, the old list will be auto-GC.

只是替换,这个变量将指向新列表,旧列表将自动GC。