Немодифицируемые карты быстро терпят неудачу - PullRequest
1 голос
/ 12 марта 2012

Карта возвращается из Collections.unmodifiableMap Fail-Fast.

Другими словами, выдает concurrentModificationException, тогда как iterating, если кто-то другой изменяет карту с помощью «изменяемого вида» карты

Ответы [ 3 ]

1 голос
/ 12 марта 2012

Вот обновленный пример, который показывает, что генерируется исключение (спасибо @ 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());
  }
  });
}
1 голос
/ 12 марта 2012

Поскольку 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)
1 голос
/ 12 марта 2012

Нет, они не работают быстро.

Хотя это и не упоминается особо, в документации API говорится, что «операции запроса на возвращенной карте« читаются »до указанной карты, и пытается изменить возвращеннуюmap ..., привести к UnsupportedOperationException ".Поскольку неизменяемая карта делегирует только исходную карту, все ограничения, касающиеся использования исходной карты, также имеют отношение к неизменяемой оболочке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...