UnmodifiableMap (коллекции Java) против ImmutableMap (Google)

Контекст

Мне нужно вернуть ссылку на карту, которую я использую для кеша данных, и я хотел бы удостовериться, что никто не может изменить их ссылку.

Вопрос

Я видел много ссылок на UnmodifiableMap и ImmutableMap в Интернете, но я не вижу ничего, сравнивая/противопоставляя их. Я полагаю, что есть веская причина, по которой Google/Guava создали свою собственную версию - может кто-нибудь сказать мне, что это такое?

Ответ 1

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

Map<String, String> realMap = new HashMap<String, String>();
realMap.put("A", "B");

Map<String, String> unmodifiableMap = Collections.unmodifiableMap(realMap);

// This is not possible: It would throw an 
// UnsupportedOperationException
//unmodifiableMap.put("C", "D");

// This is still possible:
realMap.put("E", "F");

// The change in the "realMap" is now also visible
// in the "unmodifiableMap". So the unmodifiableMap
// has changed after it has been created.
unmodifiableMap.get("E"); // Will return "F". 

В отличие от этого, ImmutableMap из Guava действительно неизменен: это настоящая копия данной карты, и никто не может каким-либо образом модифицировать эту ImmutableMap.

Обновить:

Как указано в comment, неизменяемая карта также может быть создана со стандартным API, используя

Map<String, String> immutableMap = 
    Collections.unmodifiableMap(new LinkedHashMap<String, String>(realMap)); 

Это создаст немодифицируемый вид на истинную копию данной карты и, таким образом, красиво эмулирует характеристики ImmutableMap, не добавляя зависимостей к Guava.

Ответ 2

Посмотрите на ImmutableMap JavaDoc: doc

Там есть информация об этом:

В отличие от Collections.unmodifiableMap(java.util.Map), который представляет собой вид отдельной карты, которая все еще может изменяться, экземпляр ImmutableMap содержит свои собственные данные и никогда не изменится. ImmutableMap удобен для общедоступных статических конечных карт ("константных карт"), а также позволяет легко сделать "защитную копию" карты, предоставленной вашему классу вызывающей стороной.

Ответ 3

Документация Guava

JDK предоставляет методы Collections.unmodifiableXXX, но, на наш взгляд, они могут быть громоздкими и многословными; неприятно использовать везде, где вы хотите сделать защитные копии небезопасными: возвращенные коллекции являются действительно неизменными, если никто не ссылается на исходную коллекцию неэффективно: структуры данных все еще имеют все накладные расходы на изменяемые коллекции, включая проверки параллельной модификации, дополнительное пространство в хэш-таблицы и т.д.

Ответ 4

ImmutableMap не принимает значения null, тогда как Collections.unmodifiableMap() делает. Кроме того, он не изменится после строительства, а UnmodifiableMap может. Из JavaDoc:

Постоянная, ориентированная на хэш-карта с надежным пользовательским порядком итерации. Не разрешает нулевые ключи или значения.

В отличие от Collections.unmodifiableMap(java.util.Map), который является видом отдельной карты, которая все еще может измениться, экземпляр ImmutableMap содержит свои собственные данные и никогда не изменится. ImmutableMap удобен для публичных статических окончательных карт ( "постоянные карты" ), а также позволяет легко сделать "защитную копию" карты, предоставленной вашему классу вызывающим абонентом.