有人可以分解为什么我得到 ConcurrentModificationException

问题描述

根据文档 ConcurrentModificationException 状态: ConcurrentModificationException 在不允许的情况下尝试并发修改对象时发生。

我正在尝试除锈我的 Java 大脑并制作一个霍夫曼压缩颚。 我有一个可能导致这种情况的辅助函数?当我传入 root 并将其设置为 huffmanHelper 返回的新 root 时

我的代码可能还没有做我想要的,我不需要霍夫曼的帮助或我的 bigO 故障我的问题: 我只是在幕后很好奇为什么我所做的事情在 Java 中是个问题。

谢谢

package huffman;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;

public class huffman {

public static Map<Character,Integer> frequency = new HashMap<Character,Integer>();
public static PriorityQueue<node> nodesPQ = new PriorityQueue<node>();

public static void main(String[] args) {
    
    /* get input */
    Scanner scanner = new Scanner(system.in);
    String input = scanner.nextLine();
    frequency = inputFrequency(frequency,input);
    System.out.println(frequency);
    scanner.close();
    nodesPQ = createNodes(nodesPQ,frequency);
    node a = nodesPQ.poll();
    node b = nodesPQ.poll();
    node OGroot = new node(a,b,a.getFrequency() + b.getFrequency(),null);
    node finalRoot = createBranch(nodesPQ,OGroot);
    finalRoot.inorderPrint();
}


/* counts occurrences of letters in output returns Map<Char,# of occurrences> */
public static Map<Character,Integer> inputFrequency(Map<Character,Integer> map,String input){
    /* split input into char Array */
    char[] charsArray = input.tochararray();
    
    /* fill hashmap ['Char',# of occurrences] */
    for(char i : charsArray) {
        int count = 0;                                                          
        for(char j : charsArray){
            if(i == j) {
             count++;            
            }
            map.put(i,count);                   
        }
    }
    return map;
}


/* take Map of <Character,# of occurrences> and create nodes inside PQ*/
public static PriorityQueue<node> createNodes(PriorityQueue<node> nodePQ,Map<Character,Integer> map){
            
        nodePQ = new PriorityQueue<>();  
        // create nodes inside PQ
        for (Map.Entry<Character,Integer> i : frequency.entrySet())  {
            Character character = i.getKey();
            Integer occurrences = i.getValue();
            node n = new node(null,null,occurrences,character);
            
                nodePQ.add(n);
            }        
      
        return nodePQ;
        } 


 



public static node createBranch(PriorityQueue<node> nodePQ,node root){
    node newRoot = null;
    for(node i : nodePQ) {
        node nextFrequent = nodePQ.poll();
        root = huffmanHelper(nodesPQ,root,nextFrequent);

    }
        return newRoot;
        
}
    





public static node huffmanHelper(PriorityQueue<node> nodePQ,node root,node nextFrequent){
    node newRoot = new node(nextFrequent,root.getFrequency() + nextFrequent.getFrequency(),null);
    
    //get next letter and frequency 
    return newRoot; 
        }   
}

我的堆栈跟踪:

hello my name is sam
{ =4,a=2,s=2,e=2,h=1,y=1,i=1,l=2,m=3,n=1,o=1}
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.PriorityQueue$Itr.next(PriorityQueue.java:536)
    at huffman.huffman.createBranch(huffman.java:83) - is the start of 
    forLoop in createBranch
    at huffman.huffman.main(huffman.java:26) - is node finalRoot = 
    createBranch(nodesPQ,OGroot); in main

解决方法

这一行从优先队列中移除一个元素:

    node nextFrequent = nodePQ.poll();

它发生在迭代相同优先级队列的循环内,因此被视为禁止并发修改。这会导致您的异常。

有没有更好的方法可以考虑迭代 PriorityQueue 删除项目?只是一个常规的 for 循环 w PQ.size() ?

如果你想按优先级顺序排空队列,继续取出元素直到poll()返回null(代码未测试):

    node nextFrequent = nodePQ.poll();
    while (nextFrequent != null) {
        // Do something with nextFrequent
        nextFrequent = nodePQ.poll();
    }

poll 方法检索并移除此队列的头部,如果此队列为空,则返回 null

文档链接:Queue.poll()