Collections.emptyMap()
呢?文档中提到,如果我想让我的集合不可变,就可以使用这个方法。为什么我要使用一个不可变的空集合呢?有什么意义呢?
Collections.emptyMap()
呢?文档中提到,如果我想让我的集合不可变,就可以使用这个方法。从我的个人经验来看,当API需要一组参数但你没有提供任何内容时,这种方法确实非常有用。例如,你可能有一个类似于下面的API,不允许使用空引用:
public ResultSet executeQuery(String query, Map<String, Object> queryParameters);
如果您有一个不需要任何参数的查询,那么创建一个HashMap肯定有点浪费,因为这涉及分配一个数组,而您可以只传递“空映射”,它实际上是一个常量,以 java.util.Collections
中实现的方式。有几种情况下,你更倾向于使用不可变的映射、列表、集合或其他类型的集合。
第一个,也是最重要的用例,是每当你返回查询或计算结果的集合(或列表或映射)时,你应该优先使用不可变数据结构。
在这种情况下,我更喜欢返回这些的不可变版本,因为这更清楚地反映了计算结果集的事实上的不可变性 - 无论你以后对数据做什么操作,你从查询中接收到的结果集都不应该改变。
第二个常见的用例是当你需要将参数作为方法或服务的输入提供。除非你期望输入集合被服务或方法修改(通常是一个非常糟糕的设计想法),在许多情况下,传递一个不可变集合而不是可变集合可能是合理和安全的选择。
我认为这是一种"按值传递"的惯例。
更普遍地说 - 当数据跨越模块或服务边界时,使用不可变数据结构是一种明智的做法。这使得可以更轻松地推理出(不可变的)输入/输出和可变的内部状态之间的差异。
作为一个非常有益的副作用,这增加了模块/服务的安全性和线程安全性,并确保更清晰地分离关注点。
另一个很好的理由使用Collections.empty*()
方法是它们明显缺乏冗长。在Java7之前的时代,如果你有一个通用集合,你必须在所有地方洒上通用类型注释。
只需比较以下这两个声明:
Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();
对比:
Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();
fooBarMap
分配了另一个非空值。new HashMap()
需要一个分配的对象,可能还需要一些额外的元素来存储数据,但是您只需要一个不可变空集合(列表、集合、映射或任何其他类似的集合)。当您调用的方法需要接受 Map 但不需要编辑它时,这使得它成为一个明显的选择。当你有一个返回不可变集合
的函数,但某些情况下没有数据可返回时,你可以返回emptyMap()
而不是返回null
,这样做可以使你的代码更加简洁,并且可以防止NullPointerException
的出现。
构造函数
来创建一个新的空映射
。但是,Collections
方法
提供了一些优点,可以使用静态
方法
java.util.Collections.emptyMap()
创建一个空映射
。
它们更加简洁,因为您不需要显式地输入集合的泛型类型 - 它通常是从方法调用的上下文中推断出来的。
它们更加高效,因为它们不会费力地创建新对象;它们只是重复使用现有的空且不可变的对象。这种效果通常非常微小,但偶尔(很少)是重要的。
Collections.unmodifiableMap()
相同的原因而使用它。你希望返回一个Map实例,如果用户试图修改它,则抛出异常。这只是一个特殊情况:空的Map。为什么我想要一个不可变的空集合?有何意义?
出于与想要不可变对象相同的原因。主要是因为您可以放心地睡觉,因为多个线程可以访问同一对象实例,并且它们都将看到相同的值。在集合中没有项目仍然是有效的值,您需要保持这种状态。
[NSArray array]
,它返回一个虽然无法使用但存在的对象。因此,您可以像普通对象一样操作它,而不会出现错误。 - Shane Hsu