我自己代码中的java ConcurrentModificationException
我认为我的解决方案与另一个问题的解决方案有误。它也被编辑过,所以看起来解决方案就是副本所指向的,但这显然没有解决我的问题,只是避免了出现异常(问题的表面)。由于我重新讨论这个问题的努力毫无用处,我已经开始了一个新的问题强>
我得到了一个ConcurrentModificationException
,我无法解决这个问题。所以我从一个列表中删除了一系列元素,我得到了一个错误
这就是错误:
04-Nov-2016 15:49:50.488 SEVERE [http-nio-8080-exec-199] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [Faces Servlet] in context with path [/...] threw exception [java.util.ConcurrentModificationException] with root cause
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:886)
at java.util.ArrayList$Itr.next(ArrayList.java:836)
at com.ex.PersonController.removeGroup(...)
at ....
Java代码:
public void removeGroup(int age) {
if (person != null) {
List<Person> friends = person.getFriends();
List<Person> removeFriends = new ArrayList<>();
if (friends != null) {
for (Person p : friends) {
if (p.getAge() == age) {
removeFriends.add(p);
}
}
friends.removeAll(removeFriends);
}
}
编辑: 注意this显然不能解决我的问题。虽然它避免了引发错误,但是JSF显示的结果是不正确的。在我的列表未完全更新时,JSF是否可能正在尝试刷新
EDIT2: 我认为这不是复制品。我在一些测试中遇到的错误随着this或this一起消失了(请注意,即使使用.add()方法,出于某种原因,我也遇到了相同的错误)。但是JSF仍然没有打印出我所期望的内容。我再次编写BalusC从我的问题中删除的代码,并提供更多信息:
xhtml Java代码:
<c:forEach items="#{personController.groupedPersons}" var="personG">
<h:commandButton action="#{personController.removeGroup(personG.key)}" type="submit" value="Remove" >
<f:ajax render="@form" />
</h:commandButton>
#{personG.key} - #{personG.value.size()}
</c:forEach>
因此,我第一次执行页面时,personController.groupedPersons
返回正确的人员列表(aHashMap<Integer, List<Person>>
),并将其打印出来。在这一点上,我有两组:一组是3个年龄相同的人,另一组是另一个年龄不同的人。当我点击3个年龄相同的人组成的小组时,我跟踪代码,并使用迭代器删除所有必要的人,而不引发ConcurrentModificationException
。返回的person.getFriends();
列表大小为1,这是正确的。然后ajax代码呈现表单personController.groupedPersons
再次调用,并按预期返回1个人。我已经核实过了,这就是我真正期待的回归者。但是JSF确实打印了错误的#{personG.key}
(我删除的那个)和空的#{personG.value.size()}
我知道这可能很难理解,但你能想出任何解释吗
编辑3:
这更有趣。。。如果我删除了有1个人的组,它就会被删除,然后JSF会正确地打印出有3个人的组。如果我删除包含3个人的组,他们将被删除,JSF将打印(正如我在EDIT2中所说的)我刚刚删除的组的key
,size()为空。在修改列表的同时,JSF刷新页面是否可能会出现并发问题?(这最初是我担心的,ConcurrentModificationException
来自XHTML和我的托管bean之间的并发问题,而不仅仅是托管bean的代码)。这可以解释为什么我在列表中添加而不是从列表中删除时得到了ConcurrentModificationException
# 1 楼答案
在java中,不允许遍历列表(
friends
)并在循环中从列表中删除元素(friends.remove(p)
)。这会抛出一个ConcurrentModificationException
您可以改用
Iterator
编辑:
你的
removeFriends.add(p);
方法应该有效。您不会得到与此同步的修改异常。但是,如果您的基础列表不支持removeAll
,您可能会得到一个UnsupportedOperationException
。例如Arrays.asList(...)
就是这种情况。如果您将friends
列表包装为new ArrayList(friends);
,您应该可以开始:之后不要忘记设置好友列表: