需求
數據展示有一個list,它的泛型是一個實體類,然後我們編輯界面信息,獲得了實體類中一個String字段的list,要求如果原list含有該字段的實體,則保留。如果沒有,則去掉該實體。如果新加入,則new一個實體添加!
方案
在Java list的API中有兩個方法,這裏提一下,removeAll()
和retainAll()
,兩個方法的參數都是Collection
,前者是去掉兩個集合中共有的元素,後者是保留兩個集合中共有的元素,如果兩個集合的泛型是相同的,可以藉助於這兩個方法來實現這一需求!
但是我們這裏泛型不一樣,所以只能通過遍歷比較來實現了,思路就是:遍歷源list,得到該實體類中String字段,如果新list中包含該字段,則新list去掉該字段,否則源list去掉該實體;然後遍歷新list,new出實體,添加到源list即可!
實例
實體類Entity
public class Entity{
private String a;
private String b;
public String getA() {
return a;
}
public void setA(String a) {
this.a= a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b= b;
}
}
源list-------entities
新list-------as
for (Iterator<entities> iter = entities.iterator(); iter.hasNext();) {
Entity entity=iter.next();
if (as.contains(entity.getA())) {
as.remove(entity.getA());
} else {
iter.remove();
//entities.remove(entity);
}
}
for (String a: as) {
Entity newEntity = new Entity();
newEntity.setA(a);
entities.add(newEntity);
}
問題
最開始在遍歷源list的時候,直接用的for each循環遍歷,然後刪除的時候使用entities.remove(entity);
,運行報錯java.util.ConcurrentModificationException
。查找原因,不能在遍歷集合的時候,執行該集合的刪除等操作!
Iterator 是工作在一個獨立的線程中,並且擁有一個 mutex 鎖。 Iterator 被創建之後會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往後移動的時候就找不到要迭代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。
所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象, Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性。