我认为我的解决方案错误地与另一个问题的解决方案混淆了。它也被编辑,所以看起来解决方案是副本指向的解决方案,但这显然没有解决我的问题,只是避免了引发的异常(问题的表面)。由于我重新打开这个问题的努力毫无用处,我已经开了一个新的here。
我收到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
会返回正确的人员列表(HashMap<Integer, List<Person>>
)并打印出来就好了。在这一点上,我有两组:一组3个同龄人和另一个年龄不同的人。当我点击删除 3个年龄相同的人的组时,我会跟踪代码并使用迭代器删除所有必要的人而不提出ConcurrentModificationException
。返回的person.getFriends();
列表是size = 1,这是正确的。然后ajax代码呈现表单。再次调用personController.groupedPersons
并按预期返回1个人。我已经验证了,这是我实际期望的回报者。但是JSF确实打印了错误的#{personG.key}
(我删除的那个)和null #{personG.value.size()}
。
我知道可能很难遵循,但你能想到对此的任何解释吗?
编辑3:
这甚至更有趣......如果我删除有1个人的组,它将被删除,然后JSF正确打印3人组。如果我删除了包含3个人的组,它们将被删除,JSF打印(正如我在EDIT2中所说)我刚刚删除的组key
,而size()为空。在我修改列表的同时,JSF刷新页面之间是否有可能出现并发问题? (这最初是我的担心,ConcurrentModificationException
来自XHTML和我的托管bean之间的并发问题,而不仅仅是在Managed Bean的代码中。这可以解释为什么即使我在列表中添加而不是从中删除它,我也得到ConcurrentModificationException
。
答案 0 :(得分:0)
在java中,不允许迭代列表(friends
)并在循环中从中删除元素(friends.remove(p)
)。这会引发ConcurrentModificationException
。
您可以使用Iterator
代替
Iterator<Person> iterator = friends.iterator();
while (iterator.hasNext()) {
if (iterator.next().getAge() == age) {
iterator.remove();
}
}
编辑:
使用removeFriends.add(p);
的方法应该有效。你不会得到一个并发修改异常。但是,如果基础列表不支持UnsupportedOperationException
,您最终可能会得到removeAll
。这是例如Arrays.asList(...)
的情况。如果你将friends
列表包裹起来new ArrayList(friends);
,那么你应该好好去:
public void removeGroup(int age) {
if (person != null) {
List<Person> friends = new ArrayList<>(person.getFriends());
List<Person> removeFriends = new ArrayList<>();
if (friends != null) {
for (Person p : friends) {
if (p.getAge() == age) {
removeFriends.add(p);
}
}
friends.removeAll(removeFriends);
}
}
在此之后不要忘记设置好友列表:
person.setFriends(friends);