ConcurrentModificationException的ArrayList中为
我有下面的代码:ConcurrentModificationException的ArrayList中为
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
,任何人都可以解释为什么它会发生,即使代码在同一个线程中运行?我怎么能避免它?
如果您使用“for each”循环浏览它,则不能从列表中删除。您可以使用Iterator
。替换:
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
有了:
for (Iterator<DrugStrength> it = aDrugStrengthList.iterator(); it.hasNext();) {
DrugStrength aDrugStrength = it.next();
if (!aDrugStrength.isValidDrugDescription()) {
it.remove();
}
}
java的foreach语法实际上使用Iterator,一些IDE会报告这个解决方案,并建议用foreach替换(for(MyListener listener:MyListenerList)) – 2014-12-29 09:42:14
@HugoGresse是的,但这是相反的方向。迭代器公开了对其迭代安全的'remove',这是foreach“失败”的事情。 – 2014-12-30 21:52:31
不知道,谢谢@KonradGarus – 2014-12-31 08:08:14
在遍历循环时,您试图在remove()操作中更改List值。这将导致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
并删除该项目来解决此问题。
Iterator<Item> iter = list.iterator();
while(iter.hasNext()) {
Item blah = iter.next();
if(...) {
iter.remove(); // Removes the 'current' item
}
}
应该有List接口支持这种操作的同时FPGA实现。
尝试java.util.concurrent.CopyOnWriteArrayList.class
我和HashMap有同样的问题,用Map接口的另一个实现 修正。 你应该自己测试一下。我不知道有关CopyOnWriteArrayList – idiotgenius 2010-07-06 13:35:21
我喜欢反向顺序循环,例如:
int size = list.size();
for (int i = size - 1; i >= 0; i--) {
if(remove){
list.remove(i);
}
}
,因为它不需要学习任何新的数据结构或类。
的详细信息,谢谢。我不知道这个窍门。 – 2018-01-30 14:40:21
我们可以使用并发集合类来避免ConcurrentModificationException迭代集合,例如CopyOnWriteArrayList而不是ArrayList。
检查这个职位的ConcurrentHashMap
http://www.journaldev.com/122/hashmap-vs-concurrenthashmap-%E2%80%93-example-and-exploring-iterator
[你应该停止担忧和爱情愚弄。(http://blog.*.com/2010/11/dr-strangedupe-or-how-我学习的到停止令人担忧和爱的重复数据删除/)。 – Will 2011-05-10 20:39:38
对此异常的解释是ArrayList的迭代器是一个快速失败的迭代器;即当它检测到它在同一时间的收集已被修改时它将失败(抛出异常)。与不引发并发修改异常的故障安全迭代器相比(例如,对集合ConcurrentHashMap和CopyOnWriteArrayList) – 2014-05-28 12:05:18