构建btree时出现java.util.ConcurrentModificationException

时间:2020-05-21 12:40:49

标签: java concurrency

我是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)

位于打印功能内。

0 个答案:

没有答案
相关问题