Эффективная "модификация" ImmutableMap

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

Итак, если я хочу изменить только одно значение, вот что я хотел бы иметь возможность сделать:

ImmutableMap<Guid, ImmutableMap<String, Integer>> originalMap = /* get the map */;
ImmutableMap<Guid, ImmutableMap<String, Integer>> modifiedMap =
    originalMap.cloneAndPut(key, value);

Вот что, похоже, Guava ожидает от меня:

ImmutableMap<Guid, ImmutableMap<String, Integer>> originalMap = /* get the map */;
Map<Guid, ImmutableMap<String, Integer>> mutableCopy = new LinkedHashMap<>(originalMap);
mutableCopy.put(key, value);
originalMap = ImmutableMap.copyOf(mutableCopy);
/* put the map back */

Сделав это, я получаю новую копию карты с нужной мне модификацией. Оригинальная копия остается нетронутой, и я буду использовать атомарную ссылку, чтобы вернуть ее обратно, так что вся установка потокобезопасна.

Это просто медленно.

Здесь под прикрытием происходит много бесполезного копирования. Предположим, в карте 1024 ведра. Это 1024 ведра, которые вы без необходимости создаете заново (причем по два раза), тогда как можно было бы использовать эти неизменяемые ведра как есть и клонировать только одно из них.

Итак, я думаю:

  1. Есть ли где-то зарытый метод утилиты Guava для таких вещей? (Его нет ни в Maps, ни в ImmutableMap.Builder.)

  2. Есть ли какая-нибудь другая Java-библиотека, в которой подобные вещи делаются правильно? У меня сложилось впечатление, что в Clojure есть такие вещи под капотом, но мы пока не готовы переходить на другой язык...

13
задан Trejkaz 1 February 2012 в 05:55
поделиться