集合遍历增删 并发修改异常
想要在循环遍历的过程中删除集合中的元素,问题描述如下
// 遍历map集合(UO_table),对于不满足条件1 "支持度"的项集,直接从UO_table中删除
for(ItemPair itempair : UO_table.keySet()) {
if(uo_list.size() < Info.min_sup){
UO_table.remove(itempair);
}
}
以上代码会出现并发修改异常
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5gjN2QTMxATM2EjNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
并发修改异常: 当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection(来自java API),从这里可以看出迭代器和集合是在不同线程里的。
查看资料知道了,迭代器其实在另外一个线程复制了一个一摸一样的集合进行遍历的。当用集合的remove方法删除元素时,迭代器是不会知道的,所以就会抛出异常。
修改1:用一个集合存储需要删除的记录,再remove()
ArrayList<ItemPair> listTemPairs =new ArrayList<ItemPair>(); //用一个ArrayList存储需要删除的记录
//遍历UO_table中的元素
for(ItemPair itempair : UO_table.keySet()) {
if(uo_list.size() < Info.min_sup){
listTemPairs.add(itempair);
}
}
//官方并没有实现map的removeAll方法,所以要用for()循环删除
for(ItemPair itemPair:listTemPairs) {
UO_table.remove(itemPair);
}
修改2:用一个集合存储需要删除的记录,再remove()
Iterator<ItemPair> iterator = UO_table.keySet().iterator(); //引用迭代器
while(iterator.hasNext()) { //利用迭代器进行遍历
ItemPair itempair = iterator.next();
if(uo_list.size() < Info.min_sup){
iterator.remove();
}
问题2:集合遍历增删报错
集合遍历的时候和长度有关,如果一边遍历集合一边增删,会导致长度size变化,规则发生变化,会报错。
Exception in thread “main” java.util.Concurat java.util.HashMap$HashIterator.nextEntry
for (Cat cat : set) {
if ("花花".equals(cat.getName())) {
set.remove(cat);
}
}
在单步调试中,此处cat.getName()已经获得“花花”,执行到set.remove(cat)时,是成功的,set.size 由原来3变为了2,但是再执行下一步时,直接报错,程序中断。
注意:这里的集合是无序的,但是在使用的时候,如果remove的对象是最后一个,那么不会报错,如果是前面的,就会涉及size变化,导致报错。
方案1: 删除后 break
由于此处是set集合,所以每个元素均为唯一,如果匹配出的数据为1个的话,直接在set.remove()后加break跳出即可。
for (Cat cat : set) {
if ("花花".equals(cat.getName())) {
set.remove(cat);
break;
}
}
方案2:集合存储删除元素 + removeAll()
如果匹配出的数据不唯一,有很多条,那么上面的方法就不可行了。
解决办法:采用removeAll 方法,用大集合减去小集合的方式得到结果。将匹配得到的cat对象,先存入set1中,再用set集合减去set1集合即可。
Set<Cat> set1=new HashSet<Cat>();
for (Cat cat : set) {
if (cat.getMonth()<5) {
set1.add(cat);
}
}
set.removeAll(set1);
方案3:用while和迭代器遍历
但是这里删除的时候是调用集合的remove方法,不带参数,此处应该是不会涉及到size问题。此时,就可以删除,而且遍历成功。
it = set.iterator();
while (it.hasNext()) {
Cat d = it.next();
if ("花花".equals(d.getName())) {
it.remove();
}
}
原文链接:https://blog.csdn.net/ggwxk1990/article/details/77688195