Java 如果需要集合实例,是否有任何理由选择其中一个?

Java 如果需要集合实例,是否有任何理由选择其中一个?,java,collections,Java,Collections,在JDK中,有Collection.emtpyList()和Collection.emptySet()。两者都有各自的权利。但有时所需要的只是集合的一个空的、不可变的实例。对我来说,没有理由选择一个而不是另一个,因为两者都以有效的方式实现了收集的所有操作,并且结果相同。然而,每次我需要这样一个空的收藏时,我都会在两秒钟的时间里考虑使用哪一个 我不希望从这个问题的答案中对集合框架有更深入的理解,但也许有一个微妙的原因,我可以用它来证明选择一个框架而不是另一个框架的合理性,而不再去想它 答案应至少说

在JDK中,有
Collection.emtpyList()
Collection.emptySet()
。两者都有各自的权利。但有时所需要的只是
集合的一个空的、不可变的实例。对我来说,没有理由选择一个而不是另一个,因为两者都以有效的方式实现了
收集的所有操作,并且结果相同。然而,每次我需要这样一个空的收藏时,我都会在两秒钟的时间里考虑使用哪一个

我不希望从这个问题的答案中对集合框架有更深入的理解,但也许有一个微妙的原因,我可以用它来证明选择一个框架而不是另一个框架的合理性,而不再去想它

答案应至少说明一个原因,在功能相同的上下文中,将
Collection.emtpyList()和
Collection.emtpyList()和
Collection.emptySet()中的一个置于另一个之上。如果说明的原因接近此列表的顶部,答案会更好:

  • 有一种情况下,类型系统使用一个比另一个更快乐(例如,类型推断允许使用一个比另一个更短的代码)

  • 可能在某些特殊情况下(例如,如果将空集合作为参数传递给集合框架的某些静态或实例方法,如
    Collections.sort()
    collection.removeAll()
    ),则会存在性能差异

  • 如果你仔细考虑的话,在一般情况下,选择一个比另一个“更有意义”

出现此问题的示例 为了提供一些上下文,这里有两个示例,其中我需要一个空的、不可修改的集合

这是一个API示例,它允许通过可选地指定创建过程中使用的对象集合来创建某些对象。第二个方法仅使用空集合调用第一个方法:

static void createObjectWithTheseThings(Collection<Thing> things) {
    ...
}

static void createObjectWithoutAnyThings() {
    createObjectWithTheseThings(Collections.emptyXXX());
}
class Example {
    // Initialized to an empty collection.
    private Collection<T> containedThings = Collections.emptyXXX();

    ...
}
static void createObjectWithTheseThings(集合对象){
...
}
静态void createobjectwithout anythings(){
CreateObjectWithThings(Collections.emptyXXX());
}
这是一个实体的示例,其状态由存储在非final字段中的不可变集合表示。初始化时,该字段应设置为空集合:

static void createObjectWithTheseThings(Collection<Thing> things) {
    ...
}

static void createObjectWithoutAnyThings() {
    createObjectWithTheseThings(Collections.emptyXXX());
}
class Example {
    // Initialized to an empty collection.
    private Collection<T> containedThings = Collections.emptyXXX();

    ...
}
类示例{
//初始化为空集合。
私有集合containedThings=Collections.emptyXXX();
...
}
对于emptyXXX(),它真的一点都不重要-因为它们都是空的(并且它们不可修改,所以它们总是空的),所以它一点都不重要。它们将同样适用于所有业务收集服务

看看集合真正为您提供了什么:特殊实现(实例在调用之间共享!)。所有相关操作都是虚拟实现,要么返回常量结果,要么立即抛出。甚至迭代器()也只是一个没有状态的伪对象

这根本不会有什么显著的区别

编辑:您可以说对于emptyList/Set的特殊情况,它们在Collecton接口级别的语义和复杂性方面是相同的。集合上可用的所有操作都由emptySet/List作为O(1)操作实现。因为它们都遵循集合定义的契约,所以它们在语义上也是相同的。

对于emptyXXX(),这真的一点都不重要——因为它们都是空的(并且它们是不可修改的,所以它们总是空的),这一点都不重要。它们将同样适用于所有业务收集服务

看看集合真正为您提供了什么:特殊实现(实例在调用之间共享!)。所有相关操作都是虚拟实现,要么返回常量结果,要么立即抛出。甚至迭代器()也只是一个没有状态的伪对象

这根本不会有什么显著的区别


编辑:您可以说对于emptyList/Set的特殊情况,它们在Collecton接口级别的语义和复杂性方面是相同的。集合上可用的所有操作都由emptySet/List作为O(1)操作实现。由于它们都遵循Collection定义的两个契约,因此它们在语义上也是相同的。

不幸的是,我没有一个答案可以排在您的优先级列表的首位,但如果我是您,我会选择它

Collections.emptySet
  • 类型推断是您的首要任务,但鉴于您正在寻找一个emptyCollection(),我不知道这个选择是否能够/应该影响这一点

  • 在第二个优先级上,考虑任何接收集合的api,该集合根据传入的具体对象的子接口执行不同的(意外/有意)操作。它们不是更可能根据具体实现(如ArrayList或LinkedList)提供不同的性能吗?空集合/列表不以任何空数据结构为模型;它们是虚拟实现——因此没有真正的区别

  • 基于java对这些接口的建模(无可否认,这并不理想),集合与集合非常相似。事实上,我认为这些方法几乎完全相同。从逻辑上讲,它看起来还可以,列表是添加额外排序关注点的特定子类型

现在,集合和集合看起来非常相似(java方面)带来了一个问题。如果您使用的是集合类型,很明显它不是您想要的列表。现在的问题是你确定你不是指一套。如果您没有,那么您使用的是类似于包的东西(当然必须有具体的实例,在总体逻辑中不是空的)。因此,如果您关心的是一个,那么是否应该由包api提供一个emptyBag()方法?只是想知道。顺便说一句,我会坚持使用m中的emptySet()