Какие основные операции на карте разрешены при повторении этого?

Скажем, что я повторяю карту в Java... Я не понимаю, что могу сделать для этой Карты, находясь в процессе итерации по ней. Наверное, я в основном смущен этим предупреждением в Javadoc для метода удаления интерфейса Iterator:

[...] Поведение итератора не определено, если базовая коллекция модифицирована, пока итерация выполняется каким-либо образом, кроме вызова этого метода.

Я точно знаю, что могу вызвать метод удаления без каких-либо проблем. Но, повторяя сборка карты, могу ли я:

  • Измените значение, связанное с ключом, с помощью метода put класса Map (поместить с существующим ключом)?

  • Добавить новую запись с помощью метода класса класса Map (поместить с новым ключом)?

  • Удалить запись с помощью метода удаления класса карты?

Моя догадка заключается в том, что я могу, вероятно, безопасно сделать # 1 (поставить существующий ключ), но не безопасно делать # 2 или # 3.

Заранее благодарим за какие-либо разъяснения по этому поводу.

Ответ 1

Вы можете использовать Iterator.remove(), и если вы используете итератор entrySet (из Map.Entry), вы можете использовать Map.Entry.setValue(). Все остальное и все ставки отключены - вы не должны менять карту напрямую, а некоторые карты будут не разрешать ни один из этих методов, ни оба вышеупомянутых метода.

В частности, ваши (1), (2) и (3) разрешены не.

Вы можете уйти с установкой существующего значения ключа через объект Map, но документация Set.iterator() специально исключает это и будет специфичной для реализации:

Если карта изменяется, когда выполняется итерация по множеству (за исключением операции собственного удаления итератора или операции setValue на записи карты, возвращаемой итератором), результаты итерации undefined. (выделено мной)

Ответ 2

Если вы посмотрите на класс HashMap, вы увидите поле под названием 'modCount'. Это то, как карта знает, когда она была изменена во время итерации. Любой метод, который увеличивает modCount при повторении, заставит его вызывать исключение ConcurrentModificationException.

Тем не менее, вы можете поместить значение в карту, если ключ уже существует, эффективно обновляя запись с новым значением:

 Map<String, Object> test = new HashMap<String, Object>();
 test.put("test", 1);

 for(String key : test.keySet())
 {
     test.put(key, 2); // this works!
 }

 System.out.println(test); // will print "test->2"

Когда вы спросите, можете ли вы безопасно выполнять эти операции, вам не нужно слишком беспокоиться, потому что HashMap предназначен для того, чтобы выбросить это ConcurrentModificationException, как только он столкнется с такой проблемой. Эти операции будут неэффективными; они не оставят карту в плохом состоянии.

Ответ 3

Глобального ответа нет. Интерфейс карты позволяет выбирать пользователям. К сожалению, я думаю, что все реализации в jdk используют отказоустойчивую реализацию (вот определение fail-fast, как указано в HashMap Javadoc):

Итераторы, возвращенные всем этим класс "методы просмотра коллекции" неудачно: если карта структурно изменен в любое время после итератор создается любым способом, кроме через итератор самостоятельно удалить метод, итератор будет ConcurrentModificationException. Таким образом, перед лицом параллельных модификация, итератор не работает быстро и чисто, а не рискуя произвольным, недетерминированным поведение в неопределенное время в будущее.

Ответ 4

В общем случае, если вы хотите изменить карту во время итерации по ней, вы должны использовать один из методов итератора. Я на самом деле не тестировал, будет ли # 1 работать, но другие точно не будут.