2010-11-21 57 views
11

为什么我得到不同的行为有:的Java中的addAll(集合)对新的ArrayList(集合)

  1. Collection col2 = new ArrayList(col);

  2. 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); 
} 
+7

请澄清一下,哪种确切的行为令您感到困惑? – 2010-11-21 15:36:44

+0

我的代码使用a)或b)有不同的行为。在我看来,这两次行动都会导致相同的结果,但显然他们没有。有些不同。 – marcolopes 2010-11-21 15:55:02

+2

你还是太模糊。怎么了?不会发生什么?请在您的环境中发布[SSCCE](http://sscce.org)以及(未)预期结果。 – BalusC 2010-11-21 15:56:05

回答

14

此代码:

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;

如果你使用的是吸气剂,那不会改变潜在的行为 - 你仍然保留另一个参考。

因此,如果初始分配,比如,集合包含{1,2,3},你开始了:

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

当您将的ArrayList到this.objectCollection,并与比如说填充它,{4,5,6},你会得到这样的:

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

“即” 仍然指向原始的ArrayList。

5
Collection col2 = new ArrayList(col); 

将创建一个新ArrayList大小为col.size()(+ 10%)和col所有元素复制到阵列。

Collection col2 = new ArrayList(); 

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

col2.addAll(col); 

将从col所有元素复制到col2ArrayList的端部,增大背衬阵列大小,如果需要的话。

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

最好使用第一个选项 - 这将避免至少一个额外的后备阵列扩展操作。

+0

使用第一种方法我的代码不起作用... – marcolopes 2010-11-21 15:53:34

0
public List getAdminImIdsWithValidShortNames(){ 
    return adminImIdsWithValidShortNames; 
} 

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

我觉得,容易是美丽的,只是发电机二传手/吸气方法是一个好习惯。 如果你第一次清除,那么addAll,这个清单需要清除list的所有元素,然后addAll会额外支持数组的扩展操作,那不是科学。

刚更换时,这个变量会指向新的List,旧的列表会自动GC。