【问题标题】:UnmodifiableMap (Java Collections) vs ImmutableMap (Google) [duplicate]UnmodifiableMap(Java 集合)与 ImmutableMap(Google)[重复]
【发布时间】:2014-05-03 09:55:40
【问题描述】:

上下文

我需要返回对我用于数据缓存的地图的引用,并且我想确保没有人可以修改他们的引用。

问题

我在网上看到了很多对 UnmodifiableMap 和 ImmutableMap 的引用,但我没有看到任何比较/对比它们的东西。我认为 Google/Guava 创建自己的版本是有充分理由的 - 有人可以告诉我它是什么吗?

【问题讨论】:

标签: java collections map guava


【解决方案1】:

看看 ImmutableMap JavaDoc:doc

那里有相关信息:

与 Collections.unmodifiableMap(java.util.Map) 不同,后者是仍然可以更改的单独地图的视图,ImmutableMap 的实例包含自己的数据并且永远不会更改。 ImmutableMap 对于公共静态最终映射(“常量映射”)很方便,还可以让您轻松制作由调用者提供给您的类的映射的“防御性副本”。

【讨论】:

【解决方案2】:

不可修改的地图仍可能发生变化。它只是可修改地图上的视图,通过不可修改地图可以看到支持地图中的更改。不可修改的地图只防止那些只引用不可修改的视图的人修改:

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". 

与此相反,Guava 的 ImmutableMap 是真正的不可变:它是给定地图的真正副本,任何人都不能以任何方式修改这个 ImmutableMap。

更新

正如comment 中指出的那样,也可以使用标准 API 创建不可变映射

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

这将在给定地图的真实副本上创建一个不可修改的视图,从而很好地模拟ImmutableMap 的特征,而无需将依赖项添加到 Guava。

【讨论】:

  • 1up 不仅可以链接到文档,还可以提供示例。
  • 很好的例子,谢谢你的帮助:)。
  • 值得注意的是,使用Map&lt;String, String&gt; unmodifiableMap = Collections.unmodifiableMap(new HashMap&lt;&gt;(realMap));可以实现原始backing map的真正不可变副本,无需依赖第三方库即可实现与ImmutableMap相同的结果。
  • @Lorkenpeist 好点。在实践中,我建议Collections.unmodifiableMap(new LinkedHashMap&lt;&gt;(realMap)); 保持迭代顺序不变(但在某些情况下这并不重要)。无论如何,我经常这样做,并且比ImmutableMap 更喜欢它(特别是如果 Guava 无论如何都不是依赖项)。仍然使用ImmutableMap 可能是有道理的(例如,将其用作返回类型,以在界面中显示返回的映射是不可变的,但不能在这里提出一般性建议)
  • 现在有了 Java 9,您可以使用:Map&lt;String,String&gt; unmodifiableMap = Map.ofEntries(entry("A","B"), entry("C","D"), entry("E","F"));,这对我来说更漂亮
【解决方案3】:

ImmutableMap 不接受 null 值,而 Collections.unmodifiableMap() 接受。此外它在构建后永远不会改变,而UnmodifiableMap 可能。来自 JavaDoc:

一个不可变的、基于散列的 Map,具有可靠的用户指定的迭代顺序。不允许空键或空值。

与 Collections.unmodifiableMap(java.util.Map) 不同,后者是仍然可以更改的单独地图的视图,ImmutableMap 的实例包含自己的数据并且永远不会更改。 ImmutableMap 对于公共静态最终映射(“常量映射”)很方便,还可以让您轻松地制作由调用者提供给您的类的映射的“防御性副本”。

【讨论】:

  • 很好的解释
【解决方案4】:

Guava Documentation

JDK 提供了Collections.unmodifiableXXX 方法,但在我们看来,这些方法可能笨重且冗长;在任何你想让防御性副本不安全的地方使用都不愉快:只有在没有人持有对原始集合的引用时,返回的集合才是真正不可变的 效率低下:数据结构仍然具有可变集合的所有开销,包括并发修改检查、额外空间哈希表等

【讨论】:

    猜你喜欢
    • 2020-10-11
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 2021-03-29
    • 2020-09-16
    相关资源
    最近更新 更多