英文:
ConcurrentModificationException while using Iterator<Node>
问题
I was trying to delete a row of JavaFX GridPane with JavaFX Rectangles and I found no way to do so but copying the squares above to one row below. Here is my code to do that but it keeps throwing ConcurrentModificationAcception.
static void copyAbove(int rowToBeDisappear, GridPane mainGrid) {
for (int y = (rowToBeDisappear-1); 0 <= y ; y--) {
for (int x = 0; x <= 9; x++) {
Iterator<Node> iterator = mainGrid.getChildren().iterator();
while (iterator.hasNext()) {
Node sqr = iterator.next();
if (sqr == getSqrByIndex(x,y,mainGrid)) {
iterator.remove();
mainGrid.add(sqr,x,(y+1));
}
}
}
}
}
The error
>Caused by: java.util.ConcurrentModificationException
at com.sun.javafx.collections.VetoableListDecorator$VetoableIteratorDecorator.checkForComodification(VetoableListDecorator.java:714)
at com.sun.javafx.collections.VetoableListDecorator$VetoableIteratorDecorator.hasNext(VetoableListDecorator.java:682)
at Main.copyAbove(Main.java:%local_code_row_nvm_this%)
英文:
I was trying to delete a row of JavaFX GridPane with JavaFX Rectangles and I found no way to do so but copying the squares above to one row below. Here is my code to do that but it keeps throwing ConcurrentModificationAcception.
static void copyAbove(int rowToBeDisappear, GridPane mainGrid) {
for (int y = (rowToBeDisappear-1); 0 <= y ; y--) {
for (int x = 0; x <= 9; x++) {
Iterator<Node> iterator = mainGrid.getChildren().iterator();
while (iterator.hasNext()) {
Node sqr = iterator.next();
if (sqr == getSqrByIndex(x,y,mainGrid)) {
iterator.remove();
mainGrid.add(sqr,x,(y+1));
}
}
}
}
}
The error
>Caused by: java.util.ConcurrentModificationException
at com.sun.javafx.collections.VetoableListDecorator$VetoableIteratorDecorator.checkForComodification(VetoableListDecorator.java:714)
at com.sun.javafx.collections.VetoableListDecorator$VetoableIteratorDecorator.hasNext(VetoableListDecorator.java:682)
at Main.copyAbove(Main.java:%local_code_row_nvm_this%)
答案1
得分: 3
感谢@Slaw指出我的解决方案中的缺陷。
您不能同时迭代一个迭代器并修改其支持的集合(除非通过该迭代器的remove
方法)。请将要对集合进行的结构性更改存储到临时集合中,然后在迭代之后执行它们。
如果getSqrByIndex()
保证在给定x
和y
时最多返回一个Node
,那么以下代码不会引发CME:
Node node = null;
Iterator<Node> iterator = mainGrid.getChildren().iterator();
while (iterator.hasNext()) {
Node sqr = iterator.next();
if (sqr == getSqrByIndex(x, y, mainGrid)) {
node = sqr;
}
}
if (node != null) {
mainGrid.getChildren().remove(node);
mainGrid.add(node, x, y + 1);
}
请注意,这是您的原文内容的翻译。
英文:
Thanks to @Slaw for pointing out the flaw in my solution.
You can't iterate an iterator and modify its backing collection (except through that iterator's remove
method) at the same time. Store any structural changes you'd like done on the collection to a temporary collection, then perform them after iterating.
If getSqrByIndex()
is guaranteed to return at most one Node
given an x
and a y
, then the following code will not cause CMEs:
Node node = null;
Iterator<Node> iterator = mainGrid.getChildren().iterator();
while (iterator.hasNext()) {
Node sqr = iterator.next();
if (sqr == getSqrByIndex(x,y,mainGrid)) {
node = sqr;
}
}
if (node != null) {
mainGrid.getChildren().remove(node);
mainGrid.add(node, x, y + 1);
}
答案2
得分: 0
我是一个完全的白痴,对这一点一窍不通,所以可能是错的,但为什么不使用for()循环而不是while()呢?我认为它可以保持在范围内,这样你就可以调用iterater.remove()。此外,它可能会抛出异常,因为你在迭代的同时正在向迭代器中添加对象。我建议尝试分开添加和删除对象的点。
英文:
I’m a total idiot and new to this so this may be wrong, but why not use a for() loop instead of while()? I believe it keeps it in scope so that you can call iterater.remove(). Also, it may be throwing that because you’re adding objects into your iterator at the same time that you’re iterating. I would try separating the points in which you add and remove objects.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论