当我们创建空的不可变列表/集合/映射时,是否有任何实际的应用程序/用例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当我们创建空的不可变列表/集合/映射时,是否有任何实际的应用程序/用例相关的知识,希望对你有一定的参考价值。

Java 9提供了一种创建Empty immutable List,set和Map的方法。

List list = List.of(); 
Set set = Set.of(); 
Map map = Map.of();

但是我无法理解创建空的不可变列表/集合/映射的实际用例是什么。

请帮助我理解一个空的不可变列表/ set / map的实际用例。

答案

在Java 9之前,有Collections.emptyList()Collections.emptySet()Collections.emptyMap(),它们明确地且专门用于生成不可修改的空集合。 List.of()等也可以这样做是他们的API的内部一致性问题,而不是革命性的新功能。

但你的主要问题似乎是

请帮助我理解一个空的不可变列表/ set / map的实际用例。

这真的有三个问题:

  1. 空集合的用例有哪些? 空集合很有用,因为它们是现实世界数据和算法中出现的情况的自然表示。例如,“到目前为止哪些乘客已经办理登机手续?”什么都没有。哪些任务等待发送?我可以无休止地继续下去。
  2. 不可修改的集合有哪些用例? 可以传递对不可修改集合的引用,而不用担心集合将被修改(无论如何通过该引用)。请注意,假设不可修改性得到适当记录,共享该对象的所有参与者都可以依赖它来不改变。除此之外,这对于安全地共享集合(和其他不可修改的对象)而不复制它们非常重要。
  3. 那些用例是什么用例? 空集合在现实世界的数据和算法中自然出现,因此大多数用于不可修改集合的用例都包含空集合。

此外,您没有问过,但可能忽略了这一点,虽然您无法将对象添加到不可修改的空集合中,但您可以将其替换为非空集合,或者在下次提供非空集合时使用,或者类似。

另一答案

想象一下应该对这些集合进行操作的常规数学运算。就像计算列表的交集一样。结果可以为空,在这种情况下,如果结果应该是不可变的,那么这个方法会很有用。

public List<E> intersectLists(List<E> first, List<E> second) {
    // If one is empty, return empty list
    if (first.isEmpty() || second.isEmpty()) {
        // Before Java 9: return Collections.emptyList();
        return List.of();
    }

    // Compute intersection
    ...
}

当您通过getter公开内部数据结构但不希望调用者能够操作集合时,通常会使用不可变集合。

类似的变体是不可修改的集合。如果您直接引用位于包装器下方的可变集合,则可以对这些进行操作。通过这种方式,您可以强制用户使用您指定的方法进行操作。

public Graph {
    private List<Node> nodes;

    // Other stuff
    ...

    public List<Node> getNodes() {
        // Wrap container to make list unmodifiable
        return Collections.unmodifiableList(nodes);
    }

    // User should use designated methods to manipulate instead
    public void addNode(Node node) { ... }
    public void removeNode(Node node) { ... }
}
另一答案

每当类暴露内部集合(通过公共属性,getter等)时,它必须复制整个集合或公开不可变集合,以避免调用者操纵内部数据结构。

例如,你可以有一些在内部使用但也通过getter公开的整数列表。由于列表不经常更新但经常读取,因此您决定使内部列表不可变(在每次更新时创建一个新列表)。这样你的getter就可以在不复制任何内容的情况下提交对内部列表的引用。现在,该列表迟早必须为空,需要一个空的不可变列表。

以上是关于当我们创建空的不可变列表/集合/映射时,是否有任何实际的应用程序/用例的主要内容,如果未能解决你的问题,请参考以下文章

对于更新不依赖于先前值的不可变集合,是不是有任何理由更喜欢 Interlocked 而不是 volatile?

Guava集合--Immutable(不可变)集合

编写字符串列表的不可变 F# 映射

两个不可变列表 - 如何使三重相等起作用?

Scala - 序列

快学Scala第13章----集合