2015-05-29 86 views
2

我有一个MainList有61个元素和subList的9个元素。 在subList中的9个元素中,其中8个在MainList中。Arraylist循环故障

我的目标是简单地删除这两个列表中存在的对象。

for(int i = 0; i < subList.size();i++){ 
    for(int j = 0; j < mainList.size();j++){ 
     if(subList.get(i).equals(mainList.get(j))){ 
      mainList.remove(j); 
      subList.remove(i); 

      break; 
     } 
    } 
} 

我现在面临的问题是,在for循环之后,subList仍然5元,这意味着仅for循环能够找到4个对象相似。

之后,我又写了for循环调试,如下的情况:

for(int i = 0; i < subList.size();i++){ 
    for(int j = 0; j < mainList.size();j++){ 
    if(subList.get(i).equals(mainList.get(j))){ 
      System.out.println("something"); 
     } 
    } 
} 

而且我能看到的“东西”的4倍。我想知道为什么第一个forloop不能找到所有类似的对象?

+2

不要循环使用索引并更改循环内的集合,这很可能会导致错误。改用迭代器。 – Thomas

回答

2

放弃循环并使用Collection。 removeAll

移除所有还包含在 指定的集合(可选操作)这个集合的元素。在此呼叫 返回后,此集合将不包含与 指定集合共有的元素。

由于您想从两个列表中删除重复项,您需要制作其中一个列表的副本。

List<?> sublistCopy = new ArrayList(sublist); 

subList.removeAll(mainList); 
mainList.removeAll(sublistCopy); 
3

当你从一个ArrayList中删除一个元素时,它后面的元素索引减1,所以你应该减少你的循环索引来解决这个问题。

例如,subList.remove(3);会将索引4处的元素先前移至索引3,因此为了让您的循环不跳过该元素,应该减少循环的索引。

for(int i = 0; i < subList.size();i++){ 
    for(int j = 0; j < mainList.size();j++){ 
     if(subList.get(i).equals(mainList.get(j))){ 
      mainList.remove(j); 
      subList.remove(i); 
      i--; 
      j--; // actually j-- may not be needed, since you break 
       // from the inner loop and start a new inner loop 
      break; 
     } 
    } 
} 
+0

我认为一个更优雅的选择是从sublist.size()回退到0.然后你不必减少“手动”索引 –

+1

@Pablo我认为使用Iterator的remove方法会更加优雅。那么你根本不用担心指数。 – Eran

4

为什么不使用Collection.removeAll()方法:

mainList.removeAll(subList); 

remove()“从List荷兰国际集团改变了指数。建议使用Iterator遍历并从集合中删除:

for (Iterator<...> iterator = mainList.iterator() ; iterator.hasNext() ;) { 
    Object o = iterator.next(); 
    if (subList.contains(o) ) { iterator.remove(); } 
} 

干杯,

+0

我想'mainList.removeAll(subList)'将只从mainList中删除公共对象,而不是从subList – ksap

+0

这是真的。目前尚不清楚OP是否只想移除主要元素或是否存在对称情况。无论如何,延伸到你描述的情况是微不足道的。关键是OP应该使用内置的方法。 –

0

确保两个元素是相等的(检查是否有一些白色的空间包含列表)。

for(int i=0;i<subList.size();i++){ 
    if(mainList.contains(subList.get(i)){ 
      mainList.remove(subList.get(i)); //remove the element from mainList. 
      subList.remove(i); //removes the element from subList. 

    } 
} 
0

您不应该使用索引同时修改列表。可以使用一个while循环和iterator

作为每文档:

迭代器允许调用者具有良好定义的语义迭代期间移除底层集合的元素。