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)
Кристоферу Шнайдеру: Допустим, у меня есть новый ключ в момент времени t=t', я хочу, чтобы его список содержал t'-1 нулей и "оценку" по индексу t. Но то, как я это сделал, не замечая, что каждый ключ несет один и тот же список.
Я запустил ваш код и не смог воспроизвести проблему. См. ideone.com/Gc8Xg6 — ваш код успешно выполняется до конца и не вызывает это исключение.
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:1150) в div2.A.main(A.java:27)
Я не знаю, как отформатировать свой комментарий здесь, но первые 3 соответствуют количеству входных строк (обозначаются как T). «mike 3» — это строка ввода, повторяющаяся два раза. первый раз работает нормально а второй не работает
Вместо того, чтобы добавлять соответствующую информацию в качестве комментария, вы можете редактировать свой вопрос и добавить его (полную трассировку стека) туда, где вы можете отформатировать его для удобочитаемости. Кроме того, вы можете уточнить, какая конкретная строка вашего кода вызывает исключение. Может быть, это строка 27 из A.java
?
Покажите примерный набор данных, которые вы пытаетесь прочитать. Покажите MCVE чтения этих данных и их вывода. Покажите результат, который вы ожидаете.
Седрик: Мне пришлось гуглить MCVE (оооол; спасибо, что сделал меня немного менее невежественным); Для начала вы читаете строку, в которой есть одно число, соответствующее количеству примеров (которое обозначается как T), а последующие T строк представляют собой имя, за которым следует оценка.
Проблема заключается в неправильном понимании этой строки:
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)));
Непонятно, что вы имеете в виду под словом "слепой". Вы везде используете один и тот же список (список называется
zeros
). Вы уверены, что вам не нужен уникальный список для каждого ключа на карте?