【问题标题】:Default size of ArrayListArrayList 的默认大小
【发布时间】:2016-05-18 01:12:01
【问题描述】:

查看一段代码,我注意到 ArrayList 的一个奇怪的初始化:

... = new ArrayList<..>(0);

我打开了 JavaSE 7 源代码,发现内部 elementData 数组由空数组常量 - {} 初始化。当我们将容量传递给ArrayList 构造函数时,我们所做的几乎相同——new Object[0]。所以我的问题是:新的 ArrayList(0)new ArrayList() 之间有什么区别吗? ArrayList 不应该将默认容量大小设置为 10 之类的吗?

感谢大家的回答。

【问题讨论】:

  • 显然它已被更改。如今,默认容量确实为 0。嗯,这有点语义。初始化时默认容量为 0,如果插入任何内容,则增加到 10。
  • @Gavriel 请指出我在哪里可以找到解释为什么该线程中的默认大小为 0?
  • 回答了我自己的问题:初始大小为 0,第一次使用时会跳转到 10。初始容量为 10,但它是延迟加载的。
  • 仅供参考;这篇文章对你有帮助吗:stackoverflow.com/questions/34250207/…

标签: java arrays arraylist


【解决方案1】:

有必要澄清两个定义:

大小表示列表中元素的数量。

容量表示内部数组的长度。换句话说,长度包含放置元素的位置数;

列表大小 = 2

当你使用 Arraylist 的默认构造函数创建一个列表时:

例如:

List<String> list = new ArrayList<>();
System.out.println(l.size());

输出为:0

为什么?

因为列表是空的,这是由列表的内部数组来解释的,当你使用ArrayList的默认构造函数时,内部数组是:

private static final Object[] EMPTY_ELEMENTDATA = {}; 

因此,长度值为 0(容量)的空对象数组。由于列表为空,因此大小为 0。

(元素数据的id=27)

当你将一个元素添加到列表中时,你的列表的大小会递增到 1,并且你的列表的初始内部数组会被另一个长度为 10(容量)的数组更改; (元素数据的id=30)

private static final int DEFAULT_CAPACITY = 10

(元素数据的id=30)

关于 ArrayList 的默认构造函数,API java 说: API Java:https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#ArrayList%28%29

public ArrayList()

Constructs an empty list with an initial capacity of ten.

也就是说,这个构造函数创建了一个空列表(大小等于0),初始容量为10个元素。(在列表中添加一个元素后,列表的容量变为10)

当您知道列表的大小后,您应该创建具有此大小的列表。为什么?因为add (E element) 方法的复杂性是 O(1) 摊销(当您的列表中有可用空间时),但如果您添加的元素多于列表的初始容量,则为 O(n)(最坏情况),在在这种情况下,分配了一个新数组(大小的 1.5 倍),并将旧数组复制到新数组。显然,此操作在性能和内存资源方面有成本。

所以,创建一个初始容量为 0 的列表是没有意义的。如果您不知道列表的初始容量,请使用默认构造函数,该构造函数会为您提供一个初始容量为 10 个元素的列表。

请记住,ArrayList 对大小和容量的定义是不同的:

From book Core Java 2: Fundamentals

将数组列表分配为新的ArrayList (100) // 容量为 100

不等于分配一个新数组为new Employee[100] //大小为100

数组列表的容量和数组的大小有一个重要的区别。如果你分配一个 100 的数组 条目,则该数组有 100 个插槽,可供使用。数组列表 容量为 100 个元素具有容纳 100 个元素的潜力 元素(实际上,超过 100 个,以额外的成本为代价) 重新分配);但一开始,即使在最初的 构造,数组列表根本不包含任何元素。

【讨论】:

    【解决方案2】:

    ArrayList() 将在添加第一个元素后使列表容量为 10(默认)。但是 ArrayList(0) 将保持较小的容量 - 添加第一个元素后为 1,添加第二个元素后为 2,依此类推。

    【讨论】:

      【解决方案3】:

      ArrayList 有一个内部数组来存储列表元素。

      Java 7 和 8 中的两个构造函数调用是有区别的:

      如果您执行new ArrayList&lt;&gt;(0)ArrayList 会创建一个大小为 0 的新对象数组。

      如果您使用new ArrayList&lt;&gt;()ArrayList 使用大小为 0 的静态空 Object 数组,并在您将项目添加到列表后切换到自己的私有数组。

      编辑:

      默认 ArrayList 构造函数的 Javadoc 似乎与此相矛盾。

      /**
       * Constructs an empty list with an initial capacity of ten.
       */
      public ArrayList() {
          super();
          this.elementData = EMPTY_DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // = static, empty
      }
      

      但它不会立即创建长度为10的元素数组,而是在添加元素或确保容量时:

      public void ensureCapacity(int minCapacity) {
          int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
              // any size if not default element table
              ? 0
              // larger than default for default empty table. It's already
              // supposed to be at default size.
              : DEFAULT_CAPACITY; // = 10
      
          if (minCapacity > minExpand) {
              ensureExplicitCapacity(minCapacity);
          }
      }
      

      【讨论】:

      • 谢谢,现在我明白了。我还要补充一点,该逻辑类似于延迟加载 - 在首次访问时创建非空数组。
      • 我认为在第二种情况下,容量从 10 开始,而不是从 0 开始。“ArrayList():构造一个初始容量为 10 的空列表。”更不要说static 数组了!?你是从哪里弄来的?
      • @Dedyshka 但使用new ArrayList(0) 没有意义,因为它创建了一个永远无法使用的数组
      • @Gavriel 我没有提到容量。 容量从 10 开始是什么意思?
      • @Gavriel 是的,这是案例 1。在案例 2 中,它使用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 这是静态的(查看源代码)。尽管添加项目或确保容量时,容量增量可能会有所不同。
      【解决方案4】:

      ArrayList 有 2 个构造函数。默认构造函数只是调用了 capacity=10 的另一个:

      ArrayList() {this(10);}
      
      ArrayList(capacity)
      

      容量是什么意思?这意味着分配一个大小容量的数组来保存arraylist中的项目。每当它太小而无法容纳必要的项目时,它就会被调整大小,通过创建一个更大的数组并复制所有内容(需要时间)+这意味着旧数组需要被垃圾收集(甚至更多时间)。这就是为什么正确获得正确的容量很重要的原因。尽管它适用于任何初始容量,但它可能会很慢。另一方面,拥有巨大的容量并且其中几乎没有任何项目正在浪费内存。

      注意:Arraylist(0) 将创建一个大小为 0 的数组,当您尝试添加第一个元素时,它将被丢弃并分配一个新数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-14
        • 2011-12-09
        • 1970-01-01
        • 2020-10-17
        相关资源
        最近更新 更多