我是JAVA的新手,我正在尝试构建一棵B-plus树以充分理解该算法。构建时遇到的一个问题,我面临的一个问题是 print()方法中的 java.util.ConcurrentModificationException ,我不知道如何发现并发问题的原因。
我认为这是迭代器的问题,并尝试通过其他for循环对其进行修复,但均未成功。有人可以帮忙吗?
我已经在输入示例中附加了代码。 尝试打印“ I 98 nine8”
时出现问题谢谢。
代码:
package practice;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
class pBTree<K extends Comparable<? super K>, V> {
private Node root;
int order;
public pBTree(int order) {
this.order = order;
this.root = new Node(true);
}
public void insert(K key, V value) {
root.insertValue(key, value);
}
public String print() {
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
StringBuilder sb = new StringBuilder("Tree : ");
Iterator<Node> it;
while (!queue.isEmpty()) {
Node curr = queue.remove();
sb.append("[");
for(K eachKey : curr.keys) {
sb.append(eachKey);
sb.append(" ");
it = curr.children.iterator();
while(it.hasNext()) {
queue.add(it.next());
}
}
sb.deleteCharAt(sb.length() - 1);
sb.append("]");
}
return sb.toString();
}
private class Node {
List<K> keys;
List<V> values;
List<Node> children;
boolean isRoot = false;
boolean isLeaf() {
return children.size() == 0;
}
Node() {
this.keys = new ArrayList<K>();
this.children = new ArrayList<Node>();
this.values = new ArrayList<V>();
}
Node(boolean isRoot) {
this.keys = new ArrayList<K>();
this.children = new ArrayList<Node>();
this.values = new ArrayList<V>();
this.isRoot = true;
}
int keyNumber() {
return keys.size();
}
boolean rootOverLimit() {
int rootKeyLimit = (int) (2*Math.ceil((2*order-2)/3));
return root.keys.size() > rootKeyLimit;
}
boolean childOverLimit(Node child) {
int childKeyLimit = order - 1;
return child.keys.size() > childKeyLimit;
}
void rootSplit() {
Node newRoot = new Node(true);
Node leftSibling = new Node();
Node rightSibling = new Node();
int midIdx = keyNumber() % 2 != 0 ? keyNumber() /2 : keyNumber() /2 - 1;
newRoot.keys = keys.subList(midIdx, midIdx + 1);
newRoot.values = values.subList(midIdx, midIdx + 1);
leftSibling.keys = keys.subList(0, midIdx);
leftSibling.values = values.subList(0, midIdx);
rightSibling.keys = keys.subList(midIdx + 1, keyNumber());
rightSibling.values = values.subList(midIdx + 1, keyNumber());
newRoot.children.add(leftSibling);
newRoot.children.add(rightSibling);
root = newRoot;
}
void insertValue(K key, V value) {
int loc = Collections.binarySearch(keys, key);
// if leaf node : insertion must be made at leaf node
if(isLeaf()) {
if( loc >= 0 ) {
values.set(loc, value);
// not hit and don't have children
} else {
keys.add(-loc - 1, key);
values.add(-loc - 1, value);
}
if(isRoot && rootOverLimit()) {
rootSplit();
}
// if internal node : insertion can be made in children
} else {
if( loc >= 0 ) {
values.set(loc, value);
} else {
// (1) try inserting in children
Node insertedChild = children.get(-loc-1);
insertedChild.insertValue(key, value);
// (2) check children overflow
if(childOverLimit(insertedChild)) {
// (2-1) : Transfer
Node leftSybling = children.get(-loc-2);
Node rightSybling = children.get(-loc);
// (2-2) : Split
}
}
}
}
}
}
//************* MAIN FUNCTION **************
public class BTree {
private static BufferedReader in;
private static BufferedWriter out;
private static void write_file (String message) throws IOException { out.write(message + "\n"); }
public static void main(String[] args) throws IOException {
try {
in = new BufferedReader(new FileReader("input.txt"));
out = new BufferedWriter(new FileWriter("output.txt"));
String temp = "";
String[] words;
int key;
String val;
int order = 0;
pBTree<Integer, String> bpt = null;
while((temp = in.readLine())!= null) {
words = temp.split(" ");
if(words[0].charAt(0) == '#') {
order = Integer.parseInt(words[1]);
bpt = new pBTree<Integer, String>(order);
continue;
} else {
switch(words[0]) {
case "I" :
key = Integer.parseInt(words[1]);
val = words[2];
bpt.insert(key, val);
break;
case "D" : // to be implemented
key = Integer.parseInt(words[1]);
break;
case "S" : // to be implemented
key = Integer.parseInt(words[1]);
break;
case "P" : // to be implemented
System.out.println(bpt.print());
break;
}
}
}
in.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
示例:
#1 9
I 46 abc
P
I 88 22
P
I 99 dd
P
I 200 200
P
I 120 120
P
I 300 x
P
I 400 ds
P
I 500 500
P
I 12 12
P
I 59 59
P
I 62 62
P
I 98 nine8
P
以下是问题的追溯
Tree : [46]
Tree : [46 88]
Tree : [46 88 99]
Tree : [46 88 99 200]
Tree : [46 88 99 120 200]
Tree : [46 88 99 120 200 300]
Tree : [46 88 99 120 200 300 400]
Tree : [46 88 99 120 200 300 400 500]
Tree : [12 46 88 99 120 200 300 400 500]
Tree : [12 46 59 88 99 120 200 300 400 500]
Tree : [99][12 46 59 62 88][120 200 300 400 500]
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1284)
at java.base/java.util.ArrayList$SubList.listIterator(ArrayList.java:1153)
at java.base/java.util.AbstractList.listIterator(AbstractList.java:311)
at java.base/java.util.ArrayList$SubList.iterator(ArrayList.java:1149)
at practice.pBTree.print(BTree.java:41)
at practice.BTree.main(BTree.java:183)
第41行,问题出在哪里,
for(K eachKey : curr.keys)
位于打印功能内。