ConcurrentModificationException с картой списков

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Scanner sc=new Scanner(br);
        int T=Integer.parseInt(sc.nextLine());
        Map<String, List<Integer>> scores=new HashMap<>(); 
        List<Integer> zeros= new ArrayList<>();
        for (int t=0; t<T; t++) {
            //Begin solving here
            String key=sc.next();
            int score = Integer.parseInt(sc.nextLine().trim());
            zeros.add(0);
            if (scores.containsKey(key)) {
                int curScore = scores.get(key).get(t-1);
                scores.get(key).add(curScore + score);
            } else {
                scores.put(key, zeros);
                scores.get(key).set(t, score);
            }

Приведенный выше код ошибочен, так как выдает неверный результат; список «нулей» везде имеет псевдоним (я думаю, я изучаю Java)

        if (scores.containsKey(key)) {
            int curScore = scores.get(key).get(t-1); //This line throws the exception; line 27 on my editor
            scores.get(key).add(curScore + score);
        } else {
            scores.put(key, zeros.subList(0, t+1)); //Here I fix the aliasing bug
            scores.get(key).set(t, score);
        }

Тестовый ввод

2
mike 5
mike 2

Выброшено исключение


Exception in thread "main" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1415)
    at java.base/java.util.ArrayList$SubList.get(ArrayList.java:1150)
    at div2.A.main(A.java:27)

Непонятно, что вы имеете в виду под словом "слепой". Вы везде используете один и тот же список (список называется zeros). Вы уверены, что вам не нужен уникальный список для каждого ключа на карте?

Christopher Schneider 05.05.2022 22:54

Кристоферу Шнайдеру: Допустим, у меня есть новый ключ в момент времени t=t', я хочу, чтобы его список содержал t'-1 нулей и "оценку" по индексу t. Но то, как я это сделал, не замечая, что каждый ключ несет один и тот же список.

MThiaweng 05.05.2022 23:03

Я запустил ваш код и не смог воспроизвести проблему. См. ideone.com/Gc8Xg6 — ваш код успешно выполняется до конца и не вызывает это исключение.

k314159 05.05.2022 23:11

3 Майк 3 Майк 3 Исключение в потоке "основной" java.util.ConcurrentModificationException в java.base/java.util.ArrayList$SubList.checkForComodification‌​(ArrayList.java:1415‌​) в java.base/java.util.ArrayList$ SubList.get(ArrayList.java:115‌​0) в div2.A.main(A.java:27)

MThiaweng 05.05.2022 23:17

Я не знаю, как отформатировать свой комментарий здесь, но первые 3 соответствуют количеству входных строк (обозначаются как T). «mike 3» — это строка ввода, повторяющаяся два раза. первый раз работает нормально а второй не работает

MThiaweng 05.05.2022 23:19

Вместо того, чтобы добавлять соответствующую информацию в качестве комментария, вы можете редактировать свой вопрос и добавить его (полную трассировку стека) туда, где вы можете отформатировать его для удобочитаемости. Кроме того, вы можете уточнить, какая конкретная строка вашего кода вызывает исключение. Может быть, это строка 27 из A.java?

andrewJames 05.05.2022 23:48

Покажите примерный набор данных, которые вы пытаетесь прочитать. Покажите MCVE чтения этих данных и их вывода. Покажите результат, который вы ожидаете.

Sedrick 05.05.2022 23:50

Седрик: Мне пришлось гуглить MCVE (оооол; спасибо, что сделал меня немного менее невежественным); Для начала вы читаете строку, в которой есть одно число, соответствующее количеству примеров (которое обозначается как T), а последующие T строк представляют собой имя, за которым следует оценка.

MThiaweng 06.05.2022 00:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Проблема заключается в неправильном понимании этой строки:

    scores.put(key, zeros.subList(0, t+1)); //Here I fix the aliasing bug

Вы не «исправляете ошибку псевдонимов». Метод subList не возвращает новый список. Как говорит документация, «возвращенный список поддерживается этим списком, поэтому неструктурные изменения в возвращаемом списке отражаются в этом списке, и наоборот».

Затем он говорит: «Семантика списка, возвращаемого этим методом, становится неопределенной, если резервный список (то есть этот список) структурно изменен каким-либо образом, кроме как через возвращаемый список».

Вы структурно изменяете список, поскольку добавляете элемент (zeros.add(0)) в исходный список после создания подсписка.

Вместо этого вы должны создать новый список:

    scores.put(key, new ArrayList<>(zeros.subList(0, t+1)));

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