首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java8中,为什么ArrayList的默认容量现在为零?

在Java8中,为什么ArrayList的默认容量现在为零?
EN

Stack Overflow用户
提问于 2015-12-13 18:41:13
回答 5查看 83.7K关注 0票数 99

我记得,在Java8之前,ArrayList的默认容量是10。

令人惊讶的是,默认(空)构造函数的注释仍然是:Constructs an empty list with an initial capacity of ten.

来自ArrayList.java

代码语言:javascript
复制
/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

...

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
EN

回答 5

Stack Overflow用户

发布于 2017-05-30 15:12:00

在Java8中,在我们向ArrayList对象中添加至少一个对象之前,ArrayList的默认容量是0(您可以称之为延迟初始化)。

现在的问题是为什么在JAVA 8中要做这样的更改?

答案是节省内存消耗。在实时java应用中创建数百万个数组列表对象。默认大小为10个对象意味着我们在创建时为底层数组分配10个指针(40或80字节),并用空值填充它们。空数组(填充了空值)会占用大量内存。

延迟初始化会将此内存消耗推迟到您实际使用数组列表的时刻。

请参阅下面的代码以获取帮助。

代码语言:javascript
复制
ArrayList al = new ArrayList();          //Size:  0, Capacity:  0
ArrayList al = new ArrayList(5);         //Size:  0, Capacity:  5
ArrayList al = new ArrayList(new ArrayList(5)); //Size:  0, Capacity:  0
al.add( "shailesh" );                    //Size:  1, Capacity: 10

public static void main( String[] args )
        throws Exception
    {
        ArrayList al = new ArrayList();
        getCapacity( al );
        al.add( "shailesh" );
        getCapacity( al );
    }

    static void getCapacity( ArrayList<?> l )
        throws Exception
    {
        Field dataField = ArrayList.class.getDeclaredField( "elementData" );
        dataField.setAccessible( true );
        System.out.format( "Size: %2d, Capacity: %2d%n", l.size(), ( (Object[]) dataField.get( l ) ).length );
}

Response: - 
Size:  0, Capacity:  0
Size:  1, Capacity: 10

文章Default capacity of ArrayList in Java 8详细解释了这一点。

票数 28
EN

Stack Overflow用户

发布于 2015-12-14 05:33:54

如果使用ArrayList完成的第一个操作是向addAll传递一个包含十个以上元素的集合,那么创建一个包含十个元素的初始数组以保存数组内容的任何努力都将被抛出窗口。每当向ArrayList添加内容时,都需要测试结果列表的大小是否会超过后备存储器的大小;允许初始后备存储器的大小为0而不是10将导致该测试在其第一个操作是“添加”的列表的生命周期中额外失败一次,这将需要创建初始的10项数组,但这比创建一个10项数组的开销要小,该数组最终不会被使用。

话虽如此,如果有一个重载的"addAll“,它指定了有多少项(如果有的话)可能会被添加到当前列表之后的列表中,并且可以使用它来影响其分配行为,那么在某些情况下可能会进一步提高性能。在某些情况下,将最后几个项目添加到列表中的代码会非常清楚,列表将不再需要任何空格。在很多情况下,列表只填充一次,之后就再也不会被修改了。如果点代码知道列表的最终大小将是170个元素,它有150个元素和一个大小为160的后备存储器,那么将后备存储器的大小增加到320是没有帮助的,并且将其留在大小320或将其修剪为170将比简单地让下一个分配将其增加到170的效率要低。

票数 7
EN

Stack Overflow用户

发布于 2015-12-13 19:34:47

问题是“为什么?”

内存分析检查(例如(https://www.yourkit.com/docs/java/help/inspections_mem.jsp#sparse_arrays)显示空(充满nulls)数组占用大量内存。

默认大小为10个对象意味着我们在创建时为底层数组分配10个指针(40或80字节),并用空值填充它们。真正的java应用程序会创建数百万个数组列表。

引入的修改删除了^W将此内存消耗推迟到您将实际使用数组列表的时刻。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34250207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档