Как сохранить порядок вставки в map.of factory?

Java 9 предлагает функцию Map.of() для простого создания карты с фиксированными значениями.

Проблема: я хочу создать карту, сохраняющую порядок вставки, например LinkedHashMap. Возможно ли это с этой фабрикой? По крайней мере, map.of() не сохраняет порядок ...

11
0
779
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

На самом деле не существует заводского метода, подобного LinkedHashMap::of, и у Map нет заказа как такового, поэтому единственный способ, который я вижу, - это собрать LinkedHashMap, если он вам действительно нужен.

Кстати от сам JEP:

Static factory methods on concrete collection classes (e.g., ArrayList, HashSet) have been removed from this proposal ...

There is another wrinkle, which is that static methods on classes are inherited by subclasses. Suppose a static factory method HashMap.of() were to be added. Since LinkedHashMap is a subclass of HashMap, it would be possible for application code to call LinkedHashMap.of(). This would end up calling HashMap.of(), not at all what one would expect!

Дело в том, что методы static наследуются, но не могут быть переопределены, поэтому, если бы такой метод был добавлен в HashMap, его нельзя было бы переопределить в LinkedHashMap.

Если вы можете использовать guava, вы можете использовать ImmutableMap, который задокументирован как:

An immutable, hash-based Map with reliable user-specified iteration order...

При последнем редактировании я заметил это во многих местах и ​​хотел бы узнать, есть ли у LinkedHashMap и Guava's ImmutableMap какой-либо сравнительный анализ, который я могу пройти? Но я не мог ощутить ничего, кроме неизменности.

Naman 10.09.2018 11:38

@nullpointer Мне неизвестен такой анализ, я, кажется, довольно сильно доверяю гуаве: | что мне нравится, так это то, что он построен с использованием однострочника, в отличие от Collections::unmodifiableMap, который обернул бы LinkedHashMap ...

Eugene 10.09.2018 11:49

Мой голос за ImmutableMap. Это лучшее решение IMO.

ZhekaKozlov 10.09.2018 11:57

@ZhekaKozlov Я хотел бы вернуть этот голос за предложенные имена для BiCollector ...

Eugene 10.09.2018 11:58

Фактически, методы static можно переопределить, то есть, если LinkedHashMap предоставил такие заводские методы с той же сигнатурой, что и в HashMap, они переопределили бы их, поэтому LinkedHashMap.of(…) в конечном итоге выбрал бы правильный метод, еслиLinkedHashMap предоставляет такой метод. Вы можете предположить, что это будет тот случай, когда оба класса происходят от одной и той же JRE, но как насчет ThirdPartyMap, унаследованного от любого из этих классов. Хуже всего было бы, если бы он был адаптирован для предоставления фабричных методов однажды, в результате получилась бы смесь переопределенных и непереопределенных методов в будущей версии JRE ...

Holger 12.09.2018 12:57

@Holger, чтобы быть педантичным, их можно скрыть (8.4.8.2. Скрытие (методами класса)), а не переопределить 8.4.8.1. Переопределение (методами экземпляра)), но ваша точка зрения все еще остается в силе - это можно было бы сделать, но это повлекло бы за собой значительные затраты на реализацию и обслуживание.

Hulk 12.09.2018 14:31

@Hulk действительно, и даже javac не использует правильную терминологию, например в сообщениях об ошибках. Тот раз, когда я не заглянул в спецификацию, меня тут же укусило ...

Holger 12.09.2018 14:39

@Holger, кстати, я люблю их! :) когда у вас есть final static method в родительском и такая же подпись в дочернем (без final) - javac скажет что-то вроде переопределяемого метода окончательно

Eugene 12.09.2018 14:41

Как указано в Java apidoc Map (выделено мной):

Unmodifiable Maps

The Map.of, Map.ofEntries, and Map.copyOf static factory methods provide a convenient way to create unmodifiable maps. The Map instances created by these methods have the following characteristics:

  • ...
  • The iteration order of mappings is unspecified and is subject to change.
  • ...

К сожалению, в Java API нет эквивалентного удобного метода, создающего LinkedHashMap. Если вам нужен последовательный порядок итераций, вам нужно будет вручную создать LinkedHashMap и заполнить его (и - при необходимости - обернуть его с помощью Collections.unmodifiableMap).

Рассмотрите возможность создания собственного удобного метода, который выполняет аналог Map.of, но с постоянным порядком итераций (или найдите существующую библиотеку, которая уже предоставляет это).

Вы также можете использовать vavr.io следующим образом:

Map<String, String> mapPreservingInsertionOrder = io.vavr.collection.LinkedHashMap.of("key1", "val1", "key2", "val2").toJavaMap();

Другие вопросы по теме