循环浏览列表时,我想根据条件删除列表项。请参阅下面的代码。
这给了我一个ConcurrentModification
例外。
for (Object a : list) {
if (a.getXXX().equalsIgnoreCase("AAA")) {
logger.info("this is AAA........should be removed from the list ");
list.remove(a);
}
}
如何做到这一点?
答案 0 :(得分:206)
for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ) {
String a = iter.next();
if (...) {
iter.remove();
}
}
进一步假设列表是字符串。
如前所述,需要list.iterator()
。 listIterator也可以进行一些导航。
答案 1 :(得分:67)
您需要使用Iterator
并在remove()
上致电iterator
,而不是使用for
循环。
答案 2 :(得分:28)
你不能这样做,因为你已经在它上面循环。
为了避免这种情况,请使用Iterator,它可以保证您安全地从列表中删除元素......
List<Object> objs;
Iterator<Object> i = objs.iterator();
while (i.hasNext()) {
Object o = i.next();
//some condition
i.remove();
}
答案 3 :(得分:18)
您不能也不应该在迭代时修改列表。您可以通过临时保存要删除的对象来解决此问题:
List<Object> toRemove = new ArrayList<Object>();
for(Object a: list){
if(a.getXXX().equalsIgnoreCase("AAA")){
toRemove.add(a);
}
}
list.removeAll(toRemove);
答案 4 :(得分:7)
除了这里提供的所有优秀解决方案外,我还想提供一个不同的解决方案。
我不确定您是否可以自由添加依赖项,但如果可以,您可以添加https://code.google.com/p/guava-libraries/作为依赖项。该库增加了对Java的许多基本功能操作的支持,并且可以使集合的处理更容易,更易读。
在代码中,我用T替换了List的类型,因为我不知道你的列表是什么类型的。
这个问题可以用番石榴这样解决:
List<T> filteredList = new Arraylist<>(filter(list, not(XXX_EQUAL_TO_AAA)));
然后在其他地方你将XXX_EQUAL_TO_AAA定义为:
public static final Predicate<T> XXX_EQUAL_TO_AAA = new Predicate<T>() {
@Override
public boolean apply(T input) {
return input.getXXX().equalsIgnoreCase("AAA");
}
}
然而,这可能是你的情况有点过分。随着集合的使用越多,它就会变得越来越强大。
哦,还有,你需要这些静态导入:
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Collections2.filter;
答案 5 :(得分:5)
//first find out the removed ones
List removedList = new ArrayList();
for(Object a: list){
if(a.getXXX().equalsIgnoreCase("AAA")){
logger.info("this is AAA........should be removed from the list ");
removedList.add(a);
}
}
list.removeAll(removedList);