我有一个数组列表,我想对它进行迭代。在迭代它时,我必须同时删除元素。显然,这会抛出一个java.util.ConcurrentModificationException。
处理这个问题的最佳实践是什么?我应该先克隆列表吗?
我删除的元素不是循环本身,而是代码的另一部分。
我的代码是这样的:
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething可能调用Test.removeA();
在迭代列表时,如果您想删除元素是可能的。让我们看看下面的例子,
ArrayList<String> names = new ArrayList<String>();
names.add("abc");
names.add("def");
names.add("ghi");
names.add("xyz");
我有上述名称的数组列表。我想从上面的列表中删除“def”名称,
for(String name : names){
if(name.equals("def")){
names.remove("def");
}
}
上面的代码抛出ConcurrentModificationException异常,因为您在迭代时修改了列表。
因此,要从数组列表中删除def名称,
Iterator<String> itr = names.iterator();
while(itr.hasNext()){
String name = itr.next();
if(name.equals("def")){
itr.remove();
}
}
上面的代码,通过迭代器,我们可以从数组列表中删除“def”名称,并尝试打印数组,你会看到下面的输出。
输出:[abc, ghi, xyz]
这是一个例子,我使用一个不同的列表来添加对象删除,然后我使用流。Foreach从原始列表中删除元素:
private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList();
...
private void removeOutdatedRowsElementsFromCustomerView()
{
ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime());
long diff;
long diffSeconds;
List<Object> objectsToRemove = new ArrayList<>();
for(CustomerTableEntry item: customersTableViewItems) {
diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime();
diffSeconds = diff / 1000 % 60;
if(diffSeconds > 10) {
// Element has been idle for too long, meaning no communication, hence remove it
System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName());
objectsToRemove.add(item);
}
}
objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o));
}