删除元素时ArrayList hasNext的java行为
我正在删除数组中的元素,考虑下面的代码:
private static List<Person> persons = new ArrayList<>();
//initialize the persons arraylist.
for (Person p : persons) {
if (p.getAge() < 18) {
persons.remove(p);
}
}
初始化方法:
private static void initialize() {
persons.add(new Person("Rahul", 25, Gender.MALE, Citizenship.INDIA));
persons.add(new Person("Sally", 21, Gender.FEMALE, Citizenship.USA));
persons.add(new Person("Ben", 35, Gender.MALE, Citizenship.CANADA));
persons.add(new Person("Wayne", 30, Gender.MALE, Citizenship.UK));
persons.add(new Person("ShaneYoung", 18, Gender.MALE, Citizenship.AUSTRALIA));
persons.add(new Person("Kimmo", 17, Gender.MALE, Citizenship.FINLAND));
persons.add(new Person("Simo", 17, Gender.MALE, Citizenship.FINLAND));
}
输出: [Rahul、Sally、Ben、Wayne、Shaneyong、Simo]
请注意,第二个和最后一个项目最好不要退回。 我理解,如果我们试图在遍历ArrayList时修改它的结构,我们可能会得到ConcurrentModificationException。我指的是ArrayList中的remove(对象o)。当然,这不是在迭代时删除元素的推荐方法。大多数情况下都会引发异常。但是,如果我有一个列表,其中最后一项满足我的删除条件,最后一项也满足删除条件,则不会抛出ConcurrentModificationException,因为hasNext方法返回false。hasNext()的代码是:
return cursor != size
在这种情况下,游标==大小。但请注意,最后一个元素也被跳过或未被处理。因此,除了最后一个元素外,没有异常被跳过,但也会在输出中返回
我已经研究了thisbug,还研究了它所链接的重复bug。他们似乎强调了一个稍微不同的场景
当我们调用迭代器时。移除时,似乎将光标位置调整为lastRet。所以使用迭代器。即使使用满足移除条件的第二个和最后一个项目移除,也可以正常工作,但调用fastRemove的remove(对象o)似乎没有设置此项,因此完全跳过最后一个元素
我知道迭代器。删除javadoc中提到的未指定行为,上面提到的bug中提到的注释也表明ConcurrentModificationException是尽最大努力抛出的。但是考虑到上面的代码,最后一个元素没有被过滤掉,这不是一个bug还是一个应该以更好的方式处理的场景
我注意到了这里的另一个question,但答案只解释了在我上面提到的当前实现中如何实现输出。我的问题更多的是,是否应该更改hasNext实现来处理这种情况
# 1 楼答案
当你试图在循环过程中删除列表中的元素时,它会被监听。 我通常会声明另一个临时列表,这样就可以使用removeAll方法来创建它
# 2 楼答案
根据JLS #14.14.2,增强的for循环相当于使用迭代器
正如你提到的,^{} 的javadoc非常清楚:
所以不,这不是虫子
# 3 楼答案
您可以使用
ListIterator
删除这些项,因为它有一个remove
方法:但我推荐assylias建议的Java 8解决方案: