[英]Java ConcurrentModificationException; single Thread; without for each loop
I am currently programming a BTree Algorithm.我目前正在编写 BTree 算法。 I have already implemented the functionality to add Numbers to it.
我已经实现了向其添加数字的功能。 As I went to test it, I ran into a ConcurrentModificationException.
当我去测试它时,我遇到了 ConcurrentModificationException。
I researched the issue and found hints that it mainly is due to two things:我研究了这个问题,发现主要是由于两件事:
Neither of these problems occur in my code, so I am completely lost...这些问题都没有出现在我的代码中,所以我完全迷失了......
I hope you guys can help me!我希望你们能帮助我!
Code from the "Knoten" class:来自“Knoten”类的代码:
public List<Nodes> Childnodes;
public List<Integer> Keys;
private Baum tree;
private Nodes parent;
private boolean isRoot;
public void Add(int number)
{
int lastSmallerPosition = -1;
for(int i = 0; i < Keys.size(); i++)
{
if(Keys.get(i) < number)
{
lastSmallerPosition = i;
}
else
{
if( Keys.size() < i + 1 && number == Keys.get(i + 1))
{
return;
}
break;
}
}
if(isLeaf())
{
Keys.add(lastSmallerPosition + 1, number);
if(Keys.size() > tree.maxKeys)
{
if(isRoot)
{
Nodes k1 = new Nodes(tree, this, false);
Nodes k2 = new Nodes(tree, this, false);
k1.Keys.addAll(Keys.subList(0, Keys.size()/2));
k2.Keys.addAll(Keys.subList(Keys.size()/2 + 1, Keys.size()));
Childnodes.add(k1);
Childnodes.add(k2);
int spareNumber = Keys.get(Keys.size()/2);
Keys.clear();
Keys.add(spareNumber);
}
else
{
if(parent.Keys.size() == tree.maxKeys)
{
List<Integer> list = new ArrayList<Integer>();
if(parent.Childnodes.indexOf(this) == 0)
{
int index = parent.Childnodes.indexOf(this);
list.addAll(Keys);
list.add(parent.Keys.get(index));
list.addAll(parent.Childnodes.get(index + 1).Keys);
Keys.clear();
parent.Keys.remove(index);
parent.Childnodes.remove(index + 1);
}
else
{
int index = parent.Childnodes.indexOf(this) - 1;
list.addAll(parent.Childnodes.get(index).Keys);
list.add(parent.Keys.get(index));
list.addAll(Keys);
parent.Childnodes.remove(index);
parent.Keys.remove(index);
Keys.clear();
}
int keysPerChildnode = (list.size() - tree.minKeys) / tree.minChilds;
int extraKeys = (list.size() - tree.minKeys) % tree.minChilds;
int usedExtraKeys = 0;
for(int i = 0; i < tree.minKeys - 1; i ++)
{
Childnodes.add(new Nodes(tree, this, false));
Childnodes.get(i).Keys.addAll(
list.subList(i * keysPerChildnode + usedExtraKeys + i, (i + 1) * keysPerChildnode + usedExtraKeys + i));
if(usedExtraKeys < ExtraKeys)
{
Childnodes.get(i).Keys.add(list.get((i + 1) * keysPerChildnode + usedExtraKeys + i));
usedExtraKeys++;
}
Keys.add(list.get((i + 1) * keysPerChildnode + usedExtraKeys + i));
}
Childnodes.add(new Nodes(tree, this, false));
Childnodes.get(tree.minChilds - 1).Keys.addAll(list.subList(list.size() - keysPerChildnode, list.size()));
}
else
{
Nodes k = new Nodes(tree,parent,false);
k.Keys = Keys.subList(Keys.size() / 2, Keys.size());
int NewParentKey = Keys.get(Keys.size() / 2 - 1);
Keys = Keys.subList(0, Keys.size() / 2 - 1);
int index = parent.Childnodes.indexOf(this);
parent.Keys.add(index, NewParentKey);
parent.Childnodes.add(index + 1, k);
}
}
}
}
else
{
Childnodes.get(lastSmallerPosition + 1).Add(number);
}
}
Exception:例外:
java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(Unknown Source)
at java.util.ArrayList$SubList.size(Unknown Source)
at Baum.Knoten.Add(Knoten.java:39)
at Baum.Knoten.Add(Knoten.java:175)
at Baum.Baum.Add(Baum.java:31)
at Test.BaumTest.AddTest(BaumTest.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Read the javadoc of List.subList(int fromIndex, int toIndex)
:阅读
List.subList(int fromIndex, int toIndex)
的 javadoc:
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
返回此列表中指定的 fromIndex(包含)和 toIndex(不包含)之间的部分的视图。 (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list , so non-structural changes in the returned list are reflected in this list, and vice-versa.
(如果 fromIndex 和 toIndex 相等,则返回的列表为空。)返回的列表由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。 The returned list supports all of the optional list operations.
返回的列表支持所有可选的列表操作。
[...]
[...]
The semantics of the list returned by this method become undefined if the backing list (ie, this list) is structurally modified in any way other than via the returned list.
如果支持列表(即,此列表)以除通过返回列表以外的任何方式在结构上进行了修改,则此方法返回的列表的语义将变为未定义。 (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)
(结构修改是那些改变这个列表的大小,或者以其他方式扰乱它,以致正在进行的迭代可能会产生不正确的结果。)
You need to make a copy of the sublist, if you want it to be disconnected from the original list:如果您希望它与原始列表断开连接,则需要制作子列表的副本:
new ArrayList<>(list.subList(from, to))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.