创建初始容量为 0 的 ArrayList 的优点?

Advantages of creating an ArrayList with initial capacity of 0?

我是一个有点经验的 Java 开发人员,我经常看到这样的事情

List<Integer> l = new ArrayList<Integer>(0);

我实在是看不懂。当您知道它会增长到超出容量时,创建初始容量为 0 的 ArrayList 有什么意义?

这样做有什么已知的好处吗?

根据合同,您可以通过不包含空值来避免 NullPointerExceptions。在某些情况下这是一种很好的做法,请参阅 Effective Java by Joshua Bloch 项目 43:Return 空数组或集合,而不是空值

给数组列表一个大的值(如果你会超过多少列表)总是更好的方法,因为它会减少列表的大小调整,从而优化你的执行时间。

正在用值 0 初始化数组列表创建 Empty 数组列表,reducing memory 如果您知道您的列表不会显示更多 10 内容。

对于 java 6(或 openjdk 7),不指定初始大小会给你一个初始大小设置为 10。因此,根据您使用列表的许多因素,初始化大小为 0 的列表可能会稍微增加内存 and/or 性能效率。

对于 java 7,指定初始大小 0 在功能上等同于不指定初始大小。

然而,它实际上效率较低,因为使用参数 0 调用构造函数会导致调用 new Object[0],而如果指定无参数构造函数,初始 elementData 为您的列表设置为名为 EMPTY_ELEMENTDATA.

的静态定义常量

相关代码来自ArrayList来源:

/**
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

换句话说,使用new ArrayList<Integer>(0);似乎是多余的,这样做没有任何好处,我会改用new ArrayList<Integer>();

  • 如果添加 ArrayList 真的不太可能,并且如果将 ArrayList 的大小保持在最小值很重要,那么我认为这很有用。

  • 或者如果 ArrayList 的唯一目的是作为方法的 return 值,其中 return 一个空列表是一个特殊消息给函数调用者,比如 "no results found".

  • 否则,不是真的。

它使 ArrayList 的大小(在内存中)非常小,这是一种策略,适用于当您希望变量为非 null 并准备好使用时,但不要 expect 立即填充 List。如果您希望它立即被填充,最好给它一个更大的初始值 - ArrayList 的任何 "growing" 都在内部创建一个新的原始数组,并将项目复制过来。 ArrayList 的增长是昂贵的,应该尽量减少。

或者,如果您要创建 很多 个 class 实例,每个实例都包含这些 List 属性之一。如果您不立即计划填充它们,您可以通过暂时不分配房间来节省一些内存。

不过:还有更好的办法:Collections.emptyList()。通常您会希望直接保护对该列表的访问,并且(例如)在您的 class 中提供在内部 List 上运行的特定于域的方法调用。例如,假设您有一个 School class,其中包含 List 个学生姓名。 (为简单起见,请注意此 class 不是线程安全的。

public class School {
    private List<String> studentNames = Collections.emptyList();

    public void addStudentName(String name) {
        if (studentNames.isEmpty()) {
            studentNames = new ArrayList<String>();
        }
        studentNames.add(name);
    }

    public void removeStudentName(String name) {
        studentNames.remove(name);
        if (studentNames.isEmpty()) {
            studentNames = Collections.emptyList(); // GC will deallocate the old List
        }
    }
}

如果您愿意进行 isEmpty() 检查并执行 initialization/assignment,这是创建大量空 ArrayList 实例的更好替代方法,因为 Collections.emptyList() 是一个静态实例(仅存在一个)并且不可修改。

默认情况下 ArrayList 的容量为 10,每次调整大小 +50%。

通过使用较低的初始容量,您有时(理论上)可以节省内存。另一方面,每次调整大小都很耗时。在大多数情况下,这只是抢先优化的标志。