Collections.emptyMap()vs new HashMap()

时间:2013-02-13 05:24:00

标签: java collections

我可以使用Collections.emptyMap()的哪些情况?文档说如果我希望我的集合是不可变的,我可以使用这个方法。

为什么我要一个不可变的空集合?有什么意义?

9 个答案:

答案 0 :(得分:133)

有效Java 第43项 - "Return empty arrays or collections, not null"演示了如何返回空集合,甚至可能演示使用这些emptyList(),{{1 Collections类上的方法和emptySet()方法可以获得一个空集合,它还具有不可变的额外好处。来自第15项 emptyMap()

来自Collections-emptySet-Collections-emptyList-Collections

  

它是一种编程习惯用语。这适用于不想要空变量的人。因此,在初始化集合之前,他们可以使用空集。

注意:下面的代码只是一个示例(根据您的使用情况进行更改):

"Minimize Mutability"

这些方法具有以下几个优点:

  1. 它们更简洁,因为您不需要显式地输出集合的泛型类型 - 它通常只是从方法调用的上下文中推断出来。

  2. 它们更有效率,因为它们不会打扰创建新对象;他们只是重用现有的空和不可变对象。这种影响通常非常小,但偶尔(很少,很少)很重要。

答案 1 :(得分:32)

根据我的个人经验,在API需要参数集合的情况下非常有用,但您无需提供任何参数。例如,您可能有一个类似于此的API,并且不允许空引用:

public ResultSet executeQuery(String query, Map<String, Object> queryParameters);

如果你有一个不带任何参数的查询,创建一个HashMap肯定有点浪费,它涉及分配一个数组,当你可以传入'Empty Map'时,它实际上是一个常量,它是在java.util.Collections中实现的。

答案 2 :(得分:21)

  

为什么我想要一个不可变的空集合?有什么意义?

这里有两个不同的概念,一起看时看起来很奇怪。当你分别处理这两个概念时,它会更有意义。

  • 首先,您应该尽可能使用不可变集合而不是可变集合。 immuablity的好处很好documented elsewhere

  • 其次,您应该更喜欢使用空集合而不是使用null作为标记。这是well described here。这意味着您将拥有更清晰,更易于理解的代码,并且可以减少隐藏错误的位置。

因此,当您拥有需要地图的代码时,最好传递一个空地图而不是一个空来表示没有地图。大多数情况下,当您使用地图时,最好使用不可变地图。所以这就是为什么有一个便利函数来制作一个不可变的空映射。

答案 3 :(得分:8)

有些情况下,您更喜欢使用不可变的地图,列表,集合或其他类型的集合。

首先并且可以说最重要的用例是每当您返回查询结果或返回结果集(或列表或映射)的计算时,您应该更喜欢使用不可变数据结构。

在这种情况下,我更喜欢返回这些的不可变版本,因为这更清楚地反映了计算结果集的事实不变性 - 无论您以后对数据做什么,您从您的数据中收到的结果集查询不应该改变。

第二个常见用例是指您需要提供参数作为方法或服务的输入。除非你期望输入集合被服务或方法修改(这通常是一个非常糟糕的设计理念),传入一个不可变集合而不是可变集合可能是合理和安全的选择。很多情况。

我认为它是“按价值传递”惯例。

更一般地 - 每当数据跨越模块或服务边界时,使用不可变数据结构是明智的做法。这使得更容易推理(不可变)输入/输出和可变内部状态之间的差异。

这样做的一个非常有益的副作用是提高模块/服务的安全性和线程安全性,并确保更清晰地分离关注点。

使用Collections.empty*()方法的另一个好理由是明显缺乏冗长。在Java7之前的时代,如果你有一个泛型集合,你必须在所有地方撒上泛型类型的注释。

只需比较这两个声明:

Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();

Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();

后者显然在两个重要方面取得了可读性:

  1. 在第一个声明中,空映射的整个实例化都隐藏在泛型类型声明的噪声中,使得基本上无关紧要的声明比它需要的更加神秘。
  2. 除了在右侧显着缺少泛型类型注释之外,第二个版本明确指出地图被初始化为空地图。 此外 - 知道此方法返回一个不可变的映射,现在我更容易通过搜索fooBarMap找到/fooBarMap =/在哪里分配另一个非空值。< / LI>

答案 4 :(得分:5)

首先,您可以通过参考共享来逃避。 new HashMap()等将需要一个已分配的对象,并且可能需要一些额外的元素来保存数据,但是您只需要一个不可变空集合的副本(列表,集合,映射或任何其他类似)。当你正在调用的方法需要接受Map而不需要编辑它时,这是一个明显的选择。

我建议查看Josh Bloch的 Effective Java ,它列出了一些非常好的不可变对象属性(包括线程安全性)。

答案 5 :(得分:3)

如果您有一个返回immutable collection的函数并且在某些情况下没有要返回的数据,那么它可能很有用,因此您可以返回null而不是返回emptyMap()

它使您的代码更容易,并阻止NullPointerException

答案 6 :(得分:2)

  

为什么我想要一个不可变的空集合?有什么意义?

出于同样的原因,您在某些时候会使用Collections.unmodifiableMap()。如果用户尝试修改异常,您希望返回抛出异常的Map实例。这只是一个特例:空地图。

答案 7 :(得分:2)

大多数情况下,我们使用constructor来创建新的empty map。但Collections methods使用empty map static method

创建java.util.Collections.emptyMap()提供了一些优势
  
      
  1. 它们更简洁,因为您不需要显式地输出集合的泛型类型 - 它通常只是从   方法调用的上下文。

  2.   
  3. 它们更有效率,因为它们不会打扰创建新对象;他们只是重用现有的空和不可变对象。这个   效果通常很小,但偶尔(很少,很少)   重要的。

  4.   

答案 8 :(得分:1)

  

为什么我想要一个不可变的空集合?有什么意义?

出于同样的原因,您可能需要不可变对象。主要是因为您知道多个线程可以访问对象的同一个实例并且它们都将看到相同的值,因此您可以在晚上安然入睡。在集合中没有项目仍然是一个有效的值,您可能希望维护它。