Почему Guava не предоставляет способ преобразования ключей карты

Этот вопрос уже опубликован здесь: Как преобразовать карту < String, String > к Map < Long, String > используя guava

Я думаю, что ответ CollinD уместен:

Все методы Guava для преобразования и фильтрации создают ленивые результаты... функция/предикат применяется только тогда, когда это необходимо объект используется. Они не создают копии. Из-за этого, однако, преобразование может легко нарушить требования a Set.

Скажем, например, у вас есть Map<String, String>, который содержит как "1", так и "01". Они оба различны String s, и поэтому Map может легально содержать как клавиши. Если вы преобразуете их, используя Long.valueOf(String), хотя они оба сопоставляются со значением 1. Они есть уже не отдельные ключи. Это ничего не сломает, если вы создать копию карты и добавить записи, потому что любой дубликат клавиши будут перезаписывать предыдущую запись для этого ключа. Ленько преобразованный Map, тем не менее, не будет иметь возможности принудительно использовать уникальные ключи и поэтому нарушит договор a Map.

Это правда, но на самом деле я не понимаю, почему это не сделано, потому что:

  • Когда происходит трансформация ключа, если два ключа "объединены", может быть поднято исключение во время выполнения, или мы можем передать флаг, чтобы указать, что Guava принимает любое значение нескольких возможных значений для вновь вычисленных ключ (отказоустойчивые/отказоустойчивые возможности)

  • Мы могли бы иметь Maps.transformKeys, который создает Multimap

Есть ли недостаток, который я не вижу в таких вещах?

Ответ 1

Как @CollinD предлагает, нет никакого способа сделать это ленивым способом. Чтобы реализовать get, вам нужно преобразовать все ключи с помощью своей функции преобразования (чтобы обеспечить обнаружение любых дубликатов).

Поэтому применение Function<K,NewK> до Map<K,V> отсутствует.

Можно с уверенностью применить Function<NewK,K> к карте:

V value = innerMap.get( fn.apply(newK) );

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

Function<NewK,V> newFn = Functions.compose(Functions.forMap(map), fn);