При попытке запустить этот код вылетает ошибка "ConcurrentModificationException". Полагаю потому, что в методе removeTheFirstNameDuplicates в цикле while однажды заканчиваются элементы, а я пытаюсь проверить hasNext (или не по этому???)
Пробовал
while (!map.isEmpty() && iterator.hasNext())
все равно вылетает "ConcurrentModificationException". Почему? Не понимаю. Вроде логика правильная.
* про то, что в методе Main не должно быть кода - знаю. Добавлено для тестов.
Artem
40 уровень
Почему вылетает ошибка?
Архивный
Комментарии (16)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Виталий Злобин
17 августа 2019, 06:34
Сколько людей - столько и решений, такой вывод можно сделать прочитав комментарии)
ВАЖНО: удаляем не только дубли, а все значения, которые встречаются больше раза.
вот мой подход(уверен не лучший, но рабочий и проходной):
1)Делаем лист со всеми значениями карты;
2)Делаем лист с повторами из листа со значениями;
3)проходим по листу с повторами и в каждой итерации удаляем из карты текущее значение листа.
0
Pavlo Plynko Java-разработчик в CodeGym Expert
15 декабря 2017, 13:02
В начале метода removeTheFirstNameDuplicates() нужно создать копию оригинальной мапы. Далее проходишь циклом по копии, но когда надо что-то удалить - удаляешь из оригинальной.
+1
Artem
14 декабря 2017, 20:03
Задача, кажется, решается элементарно. Поменял местами Key и Value, а потом вернул все как было - вот и отсеялись задвоения и затроения. Но нет, нужно обязательно готовый метод использовать)))
0
Сергеев ВикторMaster
14 декабря 2017, 18:48
в цикле foreach нельзя модифицировать коллекцию. Первая же ссылка в гугле по имени исключения вам все объяснит подробно (учитесь пользоваться гуглом)
0
Artem
14 декабря 2017, 19:10
Кусок кода, который вы привели - это кусок кода, данный заранее, это не я его писал. Или в этом и состоит суть урока? Увидеть ошибку?
К тому же цикл, в приведенном вами куске - это цикл по "copy", а удаление идет из "map". Так же можно делать? Или я совсем запутался?
+1
Сергеев ВикторMaster
14 декабря 2017, 19:29
да не заметил, тогда выкладывайте стек ошибки. Вылетает на 50-37 строке?
0
Artem
14 декабря 2017, 19:42
Ошибка выглядит вот так:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)
at java.util.HashMap$EntryIterator.next(HashMap.java:1471)
at java.util.HashMap$EntryIterator.next(HashMap.java:1469)
at com.javarush.task.task08.task0817.Solution.removeTheFirstNameDuplicates(Solution.java:36)
at com.javarush.task.task08.task0817.Solution.main(Solution.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
0
Сергеев ВикторMaster
14 декабря 2017, 19:47
Так же при итерации по коллекции итератором, удалять можно только методом remove класса iterator. Т.е. iterator.remove
0
Artem
14 декабря 2017, 19:59
Простите, не понял что это значит. Я ничего не удаляю сам, только отправляю map на удаление элементов в другой (уже данный задачей, написанный не мной) метод.
В первый раз нормально происходит вход в метод removeItemFromMapByValue и возвращение из него. Т.е первого человека, Жмота, он удаляет из map и записывает в temp, а вот при попытке входа в removeItemFromMapByValue на второй итерации - вылезает вышеуказанная ошибка.
0
Сергеев ВикторMaster
14 декабря 2017, 20:14
проблема в том, что в своем методе вы идете по мапе итератором (при этом удалять элемент можно только методом итератора), и где-то посередине прохода вы отдаете эту же мапу в другой метод, который удаляет элемент напрямую вызывал Map.remove()
+1
Artem
14 декабря 2017, 20:20
Но если делать так:
for (Map.Entry<String, String> pair : map.entrySet()){
removeItemFromMapByValue(map, pair.getValue());
temp.put(pair.getKey(), pair.getValue());
"типа" без итератора, то ничего не меняется, все та же ошибка.
0
--------Master
14 декабря 2017, 20:28
Следующее значение все равно пытается брать из существующего итератора, а он уже оказывается изменен в другом методе. В этом случае можно убрать из этого цикла removeItemFromMapByValue, оставить только temp.put, и уже следующим циклом пройти по значениям в temp и удалять их из основной коллекции
0
Сергеев ВикторMaster
14 декабря 2017, 20:41
цикл foreach так же использует итератор для прохода по коллекции
+1
Artem
14 декабря 2017, 20:56
Какая-то безвыходная ситуация получается.
По условию задачи из removeTheFirstNameDuplicates должен быть вызван метод removeItemFromMapByValue и туда должно быть передано значение Value.
Для того, чтобы получить значение Value необходимо использовать Итератор, но из-за удалений в методе Итератор изменяется и дальнейшая работа с ним ведет к ошибке.
Извините, что запарил :) Ну правда пятый час сижу за задачей. Кажется, что все уже перепробовал. А решения нет. И не понимаю почему.
0
--------Master
14 декабря 2017, 22:34
Так я и пытался намекнуть выше: ты можешь создать новый итератор, содержащий только интересующие значения, и вторым циклом пройти уже по нему, удаляя соответствующие записи из основной карты. У тебя уже создается карта temp, в первом цикле заполняешь ее без удаления
+1
Artem
15 декабря 2017, 22:50
Спасибо!
Все оказалось очень просто, если правильно понять задание.
Я решал задачу удаления повторов, т.е. если одинаковых Value больше одного, то я пытался найти способ удалить все КРОМЕ одного (ведь задача называется "повторы нам не нужны") и не понимал зачем нам метод, который удаляет буквально ВСЕ записи с одинаковыми Value.
А потом внимательней прочитал задание:
5.Метод removeTheFirstNameDuplicates() должен удалять из словаря ВСЕХ людей, имеющих одинаковые имена.
и задача решилась за 10 минут.
Еще раз спасибо!
0