В соответствии с документами 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
В какой строке вашего кода трассировка стека говорит, что произошла ошибка?
Давайте начнем с: Что такое трассировка стека и как я могу использовать ее для отладки ошибок моего приложения?
извините за отсутствие трассировки стека, теперь она есть
Нет, это не так, потому что он говорит, что ошибка находится в строке 26, а код, который вы вставили, имеет пустую строку в 26. Это трассировка стека, но не для этого кода, поэтому убедитесь, что ваш код минимален. воспроизводимый пример для размещения в вашем сообщении, а затем покажите трассировку стека для этого кода: не показывать трассировку стека для другого кода. Кроме того, не забывайте автоматически форматировать свой код в редакторе кода/IDE, потому что никому не нравится читать странный и даже непревзойденный код с отступами и большими участками пустых строк.
Можем ли мы предположить, что код, который вы разместили, точно такой же, как тот, который сгенерировал это исключение (здесь важны номера строк)?
Нет, вы не можете сделать такое предположение @Pshemo - см. комментарий выше.
Я собираюсь предположить, что корень находится в priorityQueue, и вы переназначаете корень в цикле for.
добавлены строки кода, связанные с трассировкой стека, дайте мне знать, если что-то неясно
Но код в вашем вопросе буквально не может иметь трассировку стека в строке 26, поэтому, даже если вы просто скопируете вставку, код, который вы показываете в своем сообщении, не соответствует коду, который вы используете локально. Это может быть неудачная вставка, это может быть случайный перевод строки и т. д. и т. д. Вот почему у нас есть рекомендации по публикации: сначала правильно отформатируйте свой код, чтобы подобные ошибки не происходили с вами. Не все, что мы просим вас исправить, является вашей ошибкой, но вы все равно несете ответственность за то, чтобы ваш пост был точным.
Если вы пытаетесь «избавить свой Java-мозг от ржавчины», хорошим началом будет использование кодовых соглашений для именования и форматирования.
Эта строка удаляет элемент из очереди приоритетов:
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()
СПАСИБО, просто, по делу, полезно и не снисходительно БЛАГОДАРЮ ВАС Оле В.В.
В.В. есть ли лучший способ перебрать PriorityQueue для удаления элементов? просто обычный цикл for w PQ.size()?
Спасибо за вашу помощь. Я решил эту проблему, изменив функцию createBranch следующим образом: следующаяЧастота = nodePQ.poll(); root = huffmanHelper (nodesPQ, root, nextFrequent); } вернуть корень; } Что забавно в этом цикле, так это то, что он заканчивается дополнительными элементами (точнее, четырьмя) в PriorityQueue (вероятно, просто странными вещами Java). Я собираюсь просто изменить цикл for на while(!nodePQ.isEmpty) и ваше предложение и посмотреть, что происходит. еще раз спасибо
отлично работает w while(!nodePQ.isEmpty) спасибо stackoverflowers
Ваша попытка for (int i = 0; i < nodePQ.size(); i++) {
завершится, когда i
вырастет до оставшегося размера. Таким образом, если с самого начала в очереди 8 или 9 элементов, когда останется 4, i
вырастет до 4 или 5, и цикл завершится. Я так понимаю, это не то, чего вы хотите.
аааа ладно, это имеет смысл, я не использовал там свой мозг. Спасибо
если вы получаете ошибки, покажите фактическую ошибку. Это означает показывать трассировку стека и объяснять, на какую часть вашего (]mcve]) кода она сопоставляется, а не просто давать ее имя и описание: помогите людям помочь вам потому что вам не нужно запускать ваш код. И как новый пользователь: добро пожаловать в Stackoverflow, но , пожалуйста, прочитайте, как правильно форматировать свой пост , а затем соответствующим образом отредактируйте свой пост. Мы приложим усилия, чтобы помочь, если вы приложите усилия, чтобы следовать правилам публикации =)