如何保留Map.of工厂中的插入顺序?

问题描述 投票:0回答:5

Java 9 提供

Map.of()
功能可以轻松创建具有固定值的地图。

问题:我想创建一个保留插入顺序的地图,如

LinkedHashMap
。那个工厂可以吗?至少
map.of()
不保留订单...

java hashmap java-9 factory-method
5个回答
18
投票

确实没有像

LinkedHashMap::of
这样的工厂方法,并且
Map
本身没有订单,所以我看到它的唯一方法是构建一个
LinkedHashMap
(如果你确实需要的话)。

顺便说一句,来自 JEP 本身

具体集合类(例如 ArrayList、HashSet)上的静态工厂方法已从该提案中删除...

还有另一个问题,那就是类的静态方法被子类继承。假设要添加一个静态工厂方法 HashMap.of()。由于 LinkedHashMap 是 HashMap 的子类,因此应用程序代码可以调用 LinkedHashMap.of()。这最终会调用 HashMap.of(),这根本不是人们所期望的!

这里的要点是

static
方法是继承的,但不可重写,因此如果将这样的方法添加到
HashMap
中,它可能不会在
LinkedHashMap
中被重写。

如果您可以使用

guava
,则可以使用
ImmutableMap
,记录为:

一个不可变的、基于哈希的映射,具有可靠的用户指定的迭代顺序......


5
投票

Map
的 Java apidoc 中所述(强调我的):

不可修改的地图

Map.of
Map.ofEntries
Map.copyOf
静态工厂方法 提供一种创建不可修改地图的便捷方法。地图 这些方法创建的实例具有以下特征:

  • ...
  • 映射的迭代顺序未指定并且可能会发生变化。
  • ...
不幸的是,Java API 中没有等效的方便方法来创建

LinkedHashMap

。如果您想要一致的迭代顺序,则需要手动创建 
LinkedHashMap
 并填充它(并且 - 如果需要 - 使用 
Collections.unmodifiableMap
 包装它)。 

考虑创建您自己的便捷方法,该方法与

Map.of

 等效,但具有一致的迭代顺序(或查找已提供此功能的现有库)。


0
投票
您还可以通过以下方式使用vavr.io:

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

0
投票
因为 JDK 中似乎没有方法可以实现您想要的功能,所以您必须自己实现它或使用现有的库。创建这样的辅助方法并不难:

public static <K, V> LinkedHashMap<K, V> of(Collection<Entry<? extends K, ? extends V>> entries) { final LinkedHashMap<K, V> map = new LinkedHashMap<>(); entries.forEach(entry -> map.put(entry.getKey(), entry.getValue())); return map; }
然后你可以像这样使用它:

of(List.of(Map.entry("Hello", "World"), Map.entry("Goodnight", "Moon")));
该解决方案相对于 JDK 中的 Map.of 的优点在于,键值对作为条目对提供,而不仅仅是通过参数索引作为丢失对。


0
投票
如果你不关心顺序,而只需要它保持一致,你可以使用像

TreeMap

这样的排序映射与
Map.of
结合使用

new TreeMap<>(Map.of("key1", "value1", "key0", "value0", "key3", "value3"))
这应该始终返回一个一致的映射,其中键已排序。

注意:如果您需要它不可修改,则需要用类似的东西包装它

Collections.unmodifiableMap(<<<TreeMap Here>>>)
    
© www.soinside.com 2019 - 2024. All rights reserved.