我可以使用哪些情况Collections.emptyMap()
?文档说如果我希望我的集合是不可变的,我可以使用这种方法。
为什么我想要一个不可变的空集合?重点是什么?
我可以使用哪些情况Collections.emptyMap()
?文档说如果我希望我的集合是不可变的,我可以使用这种方法。
为什么我想要一个不可变的空集合?重点是什么?
来自Effective Java的 Item #43 -"Return empty arrays or collections, not null"
演示了返回一个空集合,甚至可能演示了使用 Collections 类上的这些emptyList()
、、emptySet()
和emptyMap()
方法来获得一个空集合,该集合还具有不可变的额外好处。来自 第 15 条 "Minimize Mutability"
。
来自Collections-emptySet-Collections-emptyList-Collections
它是一种编程习惯。这适用于不想要空变量的人。所以在集合被初始化之前,他们可以使用空集合。
注意:下面的代码只是一个示例(根据您的用例进行更改):
private Set myset = Collections.emptySet();
void initSet() {
myset = new HashSet();
}
void deleteSet() {
myset = Collections.emptySet();
}
这些方法有几个优点:
它们更简洁,因为您不需要显式输入集合的泛型类型——它通常只是从方法调用的上下文中推断出来的。
它们更高效,因为它们不需要创建新对象;他们只是重新使用现有的空且不可变的对象。这种影响通常非常轻微,但偶尔(嗯,很少)很重要。
诚然,就我个人的经验而言,它在 API 需要一组参数但您没有提供任何东西的情况下非常有用。例如,您可能有一个看起来像这样的 API,并且不允许空引用:
public ResultSet executeQuery(String query, Map<String, Object> queryParameters);
如果您有一个不带任何参数的查询,那么创建一个涉及分配数组的 HashMap 肯定有点浪费,当您可以传入实际上是一个常量的“空映射”时,它的实现方式在java.util.Collections
.
为什么我想要一个不可变的空集合?重点是什么?
这里有两个不同的概念,放在一起看时会显得很奇怪。当您分别处理这两个概念时,它更有意义。
首先,您应该尽可能使用不可变集合而不是可变集合。不变性的好处在其他地方有很好的记载。
其次,您应该更喜欢使用空集合而不是使用 null 作为标记。这在这里有很好的描述。这意味着您将拥有更清晰、更易于理解的代码,并且隐藏错误的地方更少。
因此,当您有需要映射的代码时,最好传递一个空映射而不是 null 来指示不存在映射。而且大多数情况下,当您使用地图时,最好使用不可变地图。所以这就是为什么有一个方便的函数来制作一个不可变的空地图。
在某些情况下,您更喜欢使用不可变映射、列表、集合或其他类型的集合。
第一个并且可以说是最重要的用例是,每当您返回将返回结果集(或列表或映射)的查询或计算的结果时,您应该更喜欢使用不可变数据结构。
在这种情况下,我更喜欢返回这些的不可变版本,因为这更清楚地反映了计算结果集的事实不变性 - 无论您以后如何处理数据,您从查询中收到的结果集都不应该改变。
第二个常见用例是当您需要提供参数作为方法或服务的输入时。除非您希望输入集合被服务或方法修改(这通常是一个非常糟糕的设计理念),否则在许多情况下传入不可变集合而不是可变集合可能是合理且安全的选择。
我认为它是“按价值传递”的约定。
更一般地说,当数据跨越模块或服务边界时,使用不可变数据结构是一种明智的做法。这使得推理(不可变)输入/输出和可变内部状态之间的差异变得更加容易。
这样做的一个非常有益的副作用是提高了模块/服务的安全性和线程安全性,并确保了更清晰的关注点分离。
使用方法的另一个好理由Collections.empty*()
是它们明显不冗长。在 Java7 之前的时代,如果你有一个泛型集合,你必须在所有地方都使用泛型类型注解。
只需比较这两个声明:
Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();
相对:
Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();
后者显然在两个重要方面赢得了可读性:
fooBarMap
值的分配位置。/fooBarMap =/
一方面,您可以摆脱参考共享。一个new HashMap()
etc 将需要一个分配的对象,可能还需要一些额外的元素来保存数据,但您只需要一个不可变的空集合(列表、集合、映射或任何其他此类)的副本。当您调用的方法需要接受 Map 但不需要编辑它时,这使它成为一个明显的选择。
我建议查看 Josh Bloch 的Effective Java,它列出了一些非常好的不可变对象的属性(包括线程安全)。
immutable collection
当您有一个返回 an 的函数并且在某些情况下没有要返回的数据时,它可能很有用,因此null
您可以返回而不是返回emptyMap()
它使您的代码更容易并防止NullPointerException
大多数时候我们使用 aconstructor
来创建一个新的empty map
. 但是Collections
methods
提供了几个优点来创建一个empty map
使用static
method
java.util.Collections.emptyMap()
它们更简洁,因为您不需要显式输入集合的泛型类型——它通常只是从方法调用的上下文中推断出来的。
它们更高效,因为它们不需要创建新对象;他们只是重新使用现有的空且不可变的对象。这种影响通常非常轻微,但偶尔(嗯,很少)很重要。
为什么我想要一个不可变的空集合?重点是什么?
出于同样的原因,您会Collections.unmodifiableMap()
在某些时候使用。如果用户尝试修改它,您希望返回一个引发异常的 Map 实例。这只是一个特例:空地图。
为什么我想要一个不可变的空集合?重点是什么?
出于同样的原因,您可能需要不可变对象。主要是因为您知道多个线程可以访问对象的同一实例并且它们都将看到相同的值,因此您可以在晚上安然入睡。集合中没有项目仍然是一个有效值,您希望保持该值。