Логическая разбивка ConcurrentModificationException

В соответствии с документами ConcurrentModificationException заявляет: ConcurrentModificationException возникает, когда объект пытаются изменить одновременно, когда это недопустимо.

Я пытаюсь избавиться от ржавчины на некоторых концепциях Java и создать приложение сжатия Хаффмана.
У меня есть вспомогательная функция, которая, как я полагаю, вызывает это, но я не уверен, почему. Когда я передаю root и устанавливаю новый корень, который возвращается huffmanHelper

(мой код, вероятно, еще не полностью делает то, что я хочу)
Мой вопрос: * за кулисами, почему я пытаюсь решить проблему в 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,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

В какой строке вашего кода трассировка стека говорит, что произошла ошибка?

Ole V.V. 26.12.2020 19:19

извините за отсутствие трассировки стека, теперь она есть

Slowly_Learning 26.12.2020 19:25

Нет, это не так, потому что он говорит, что ошибка находится в строке 26, а код, который вы вставили, имеет пустую строку в 26. Это трассировка стека, но не для этого кода, поэтому убедитесь, что ваш код минимален. воспроизводимый пример для размещения в вашем сообщении, а затем покажите трассировку стека для этого кода: не показывать трассировку стека для другого кода. Кроме того, не забывайте автоматически форматировать свой код в редакторе кода/IDE, потому что никому не нравится читать странный и даже непревзойденный код с отступами и большими участками пустых строк.

Mike 'Pomax' Kamermans 26.12.2020 19:26

Можем ли мы предположить, что код, который вы разместили, точно такой же, как тот, который сгенерировал это исключение (здесь важны номера строк)?

Pshemo 26.12.2020 19:27

Нет, вы не можете сделать такое предположение @Pshemo - см. комментарий выше.

Amir Afghani 26.12.2020 19:28

Я собираюсь предположить, что корень находится в priorityQueue, и вы переназначаете корень в цикле for.

Amir Afghani 26.12.2020 19:29

добавлены строки кода, связанные с трассировкой стека, дайте мне знать, если что-то неясно

Slowly_Learning 26.12.2020 19:30

Но код в вашем вопросе буквально не может иметь трассировку стека в строке 26, поэтому, даже если вы просто скопируете вставку, код, который вы показываете в своем сообщении, не соответствует коду, который вы используете локально. Это может быть неудачная вставка, это может быть случайный перевод строки и т. д. и т. д. Вот почему у нас есть рекомендации по публикации: сначала правильно отформатируйте свой код, чтобы подобные ошибки не происходили с вами. Не все, что мы просим вас исправить, является вашей ошибкой, но вы все равно несете ответственность за то, чтобы ваш пост был точным.

Mike 'Pomax' Kamermans 26.12.2020 19:44

Если вы пытаетесь «избавить свой Java-мозг от ржавчины», хорошим началом будет использование кодовых соглашений для именования и форматирования.

chrylis -cautiouslyoptimistic- 26.12.2020 20:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
11
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эта строка удаляет элемент из очереди приоритетов:

    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()

СПАСИБО, просто, по делу, полезно и не снисходительно БЛАГОДАРЮ ВАС Оле В.В.

Slowly_Learning 26.12.2020 19:41

В.В. есть ли лучший способ перебрать PriorityQueue для удаления элементов? просто обычный цикл for w PQ.size()?

Slowly_Learning 26.12.2020 19:50

Спасибо за вашу помощь. Я решил эту проблему, изменив функцию createBranch следующим образом: следующаяЧастота = nodePQ.poll(); root = huffmanHelper (nodesPQ, root, nextFrequent); } вернуть корень; } Что забавно в этом цикле, так это то, что он заканчивается дополнительными элементами (точнее, четырьмя) в PriorityQueue (вероятно, просто странными вещами Java). Я собираюсь просто изменить цикл for на while(!nodePQ.isEmpty) и ваше предложение и посмотреть, что происходит. еще раз спасибо

Slowly_Learning 27.12.2020 20:29

отлично работает w while(!nodePQ.isEmpty) спасибо stackoverflowers

Slowly_Learning 27.12.2020 20:38

Ваша попытка for (int i = 0; i < nodePQ.size(); i++) { завершится, когда i вырастет до оставшегося размера. Таким образом, если с самого начала в очереди 8 или 9 элементов, когда останется 4, i вырастет до 4 или 5, и цикл завершится. Я так понимаю, это не то, чего вы хотите.

Ole V.V. 27.12.2020 21:13

аааа ладно, это имеет смысл, я не использовал там свой мозг. Спасибо

Slowly_Learning 27.12.2020 23:15

Другие вопросы по теме