Java ArrayList的ConcurrentModificationException
我有以下代码:Java ArrayList的ConcurrentModificationException,java,collections,concurrency,Java,Collections,Concurrency,我有以下代码: private String toString(List<DrugStrength> aDrugStrengthList) { StringBuilder str = new StringBuilder(); for (DrugStrength aDrugStrength : aDrugStrengthList) { if (!aDrugStrength.isValidDrugDescription()) {
private String toString(List<DrugStrength> aDrugStrengthList) {
StringBuilder str = new StringBuilder();
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
str.append(aDrugStrengthList);
if (str.indexOf("]") != -1) {
str.insert(str.lastIndexOf("]"), "\n " );
}
return str.toString();
}
当我尝试运行它时,我得到ConcurrentModificationException,有人能解释为什么会发生这种情况吗,即使代码运行在同一个线程中?我怎样才能避免它呢?在循环中迭代时,您试图在删除操作中更改列表值。这将导致ConcurrentModificationException 遵循下面的代码,这将实现您想要的,但不会抛出任何异常
private String toString(List aDrugStrengthList) {
StringBuilder str = new StringBuilder();
List removalList = new ArrayList();
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
removalList.add(aDrugStrength);
}
}
aDrugStrengthList.removeAll(removalList);
str.append(aDrugStrengthList);
if (str.indexOf("]") != -1) {
str.insert(str.lastIndexOf("]"), "\n " );
}
return str.toString();
}
正如其他答案所说,您不能从正在迭代的集合中删除项。您可以通过显式使用迭代器并删除其中的项来解决这个问题
Iterator<Item> iter = list.iterator();
while(iter.hasNext()) {
Item blah = iter.next();
if(...) {
iter.remove(); // Removes the 'current' item
}
}
如果使用for each循环浏览列表,则无法将其从列表中删除。您可以使用迭代器。替换:
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
与:
应该有一个支持这种操作的列表接口的并发实现
尝试java.util.concurrent.CopyOnWriteArrayList.class我喜欢循环的相反顺序,例如:
int size = list.size();
for (int i = size - 1; i >= 0; i--) {
if(remove){
list.remove(i);
}
}
因为它不需要学习任何新的数据结构或类。我们可以使用并发集合类来避免在迭代集合时出现ConcurrentModificationException,例如CopyOnWriteArrayList而不是ArrayList 查看这篇文章中的ConcurrentHashMap
HashMap也有同样的问题,通过Map接口的另一个实现修复了这个问题。我不知道关于CopyonWritearraylist的详细信息对这个异常的解释是ArrayList的迭代器是一个快速失效的迭代器;i、 e.当它检测到它的集合在同一时间被修改时,它将失败抛出异常。与不会引发并发修改异常的故障安全迭代器(例如,在集合ConcurrentHashMap和CopyonWritearraylist上)相比,java的foreach语法实际上使用迭代器,一些IDE会报告此解决方案,并建议用foreach forMyListener侦听器替换:MyListenerList@HugoGresse对但这是相反的方向。迭代器公开了对其迭代来说是安全的删除,这是foreach丢失的。
int size = list.size();
for (int i = size - 1; i >= 0; i--) {
if(remove){
list.remove(i);
}
}