Карта возвращается из Collections.unmodifiableMap Fail-Fast.
Другими словами, он выбрасывает concurrentModificationException
в то время как iterating
, если кто-то другой изменяет карту с "изменяемым видом" карты
3 ответа
Поскольку API не определяет поведение, он зависит от реализации, то есть может варьироваться в зависимости от того, какую среду выполнения Java вы используете.
Для среды выполнения Sun Java 6 похоже, что поведение будет унаследовано от карты, которую вы обертываете. Это разумное поведение, хотя, как я уже сказал, не гарантируется во всех реализациях.
Изменить - тестовый пример для Sun Java 6:
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class TestUnmod {
public static void main(String[] args) {
Map<String,String> map = new HashMap();
map.put("a", "a");
map.put("b", "b");
map.put("c", "c");
Map<String,String> unmod = Collections.unmodifiableMap(map);
Iterator<String> it = unmod.values().iterator();
System.out.println(it.next());
map.put("d", "d");
System.out.println(it.next());
}
}
Выход:
b
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$ValueIterator.next(HashMap.java:822)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1010)
at TestUnmod.main(TestUnmod.java:18)
Нет, они не безотказны.
Хотя это особо не упоминается, в документации API указано, что «операции запроса на возвращенной карте« читаются »в указанную карту и попытки изменить возвращенную карту ... приводят к исключению UnsupportedOperationException». Поскольку неизменяемая карта делегирует только исходную карту, все ограничения, касающиеся использования исходной карты, также актуальны для неизменяемой оболочки.
Вот обновленный пример, который показывает, что возникает исключение (спасибо, @jarnbjo):
final Map<Integer, String> original = new HashMap<Integer, String>();
final int capacity = 1000 * 100;
for (int i = 0; i < capacity; i++) {
original.put(i, UUID.randomUUID().toString());
}
final Map<Integer, String> unmodifiable = Collections.unmodifiableMap(original);
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int k = 0; k < 5; k++) {
executor.execute(new Runnable() {
@Override
public void run() {
Random r = new Random();
int c = original.size();
for (int i = c; i < c + 1000; i++) {
original.put(i, UUID.randomUUID().toString());
}
}
});
executor.execute(new Runnable() {
@Override
public void run() {
StringBuilder sb = new StringBuilder();
for (Map.Entry<Integer, String> entry : unmodifiable.entrySet()) {
sb.append(entry.getValue()).append(' ');
}
System.out.println("sb.toString().length() = " + sb.toString().length());
}
});
}
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].