热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

AsIrecall,beforeJava8,thedefaultcapacityofArrayListwas10.我记得,在Java8之前,ArrayList的默认容量是1

As I recall, before Java 8, the default capacity of ArrayList was 10.

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

Surprisingly, the comment on the default (void) constructor still says: Constructs an empty list with an initial capacity of ten.

令人惊讶的是,对default(void)构造函数的注释仍然说:构造一个初始容量为10的空列表。

From ArrayList.java:

来自ArrayList.java:

/**
 * 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;
}

6 个解决方案

#1


87  

Technically, it's 10, not zero, if you admit for a lazy initialisation of the backing array. See:

从技术上讲,如果您承认后备阵列的延迟初始化,则为10,而不是零。看到:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

where

哪里

/**
 * Default initial capacity.
 */
private static final int DEFAULT_CAPACITY = 10;

What you're referring to is just the zero-sized initial array object that is shared among all initially empty ArrayList objects. I.e. the capacity of 10 is guaranteed lazily, an optimisation that is present also in Java 7.

你所指的只是在所有最初空的ArrayList对象之间共享的零大小的初始数组对象。即懒惰保证了10的容量,Java 7中也存在一个优化。

Admittedly, the constructor contract is not entirely accurate. Perhaps this is the source of confusion here.

不可否认,构造函数合同并不完全准确。也许这就是混乱的根源。

Background

Here's an E-Mail by Mike Duigou

这是Mike Duigou的电子邮件

I have posted an updated version of the empty ArrayList and HashMap patch.

我发布了空ArrayList和HashMap补丁的更新版本。

http://cr.openjdk.java.net/~mduigou/JDK-7143928/1/webrev/

http://cr.openjdk.java.net/~mduigou/JDK-7143928/1/webrev/

This revised implementation introduces no new fields to either class. For ArrayList the lazy allocation of the backing array occurs only if the list is created at default size. According to our performance analysis team, approximately 85% of ArrayList instances are created at default size so this optimization will be valid for an overwhelming majority of cases.

此修订的实现不会为任何一个类引入新字段。对于ArrayList,仅当列表以默认大小创建时,才会发生后备阵列的延迟分配。根据我们的性能分析团队,大约85%的ArrayList实例是以默认大小创建的,因此这种优化对于绝大多数情况都是有效的。

For HashMap, creative use is made of the threshold field to track the requested initial size until the bucket array is needed. On the read side the empty map case is tested with isEmpty(). On the write size a comparison of (table == EMPTY_TABLE) is used to detect the need to inflate the bucket array. In readObject there's a little more work to try to choose an efficient initial capacity.

对于HashMap,创建使用阈值字段来跟踪请求的初始大小,直到需要存储桶阵列。在读取端,使用isEmpty()测试空映射大小写。在写入大小上,使用(table == EMPTY_TABLE)的比较来检测是否需要给桶阵列充气。在readObject中,尝试选择有效的初始容量还有一些工作要做。

From: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-April/015585.html

来自:http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-April/015585.html

#2


8  

In java 8 default capacity of ArrayList is 0 until we add at least one object into the ArrayList object (You can call it lazy initialization). Please see below code for help.

在java 8中,ArrayList的默认容量为0,直到我们将至少一个对象添加到ArrayList对象中(您可以将其称为延迟初始化)。请参阅以下代码以获取帮助。

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

Now question is why this change has been done in JAVA 8?

现在问题是为什么在JAVA 8中完成了这个改变?

Answer is to save memory consumption. Millions of array list objects are created in real time java applications. Default size of 10 objects means that we allocate 10 pointers (40 or 80 bytes) for underlying array at creation and fill them in with nulls. An empty array (filled with nulls) occupy lot of memory .

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

Lazy initialization postpones this memory consumption till moment you will actually use the array list.

延迟初始化会推迟此内存消耗,直到您实际使用数组列表为止。

Article Default capacity of ArrayList in Java 8 explains it in details.

文章Java 8中ArrayList的默认容量详细解释了它。

#3


6  

If the very first operation that is done with an ArrayList is to pass addAll a collection which has more than ten elements, then any effort put into creating an initial ten-element array to hold the ArrayList's contents would be thrown out the window. Whenever something is added to an ArrayList it's necessary to test whether the size of the resulting list will exceed the size of the backing store; allowing the initial backing store to have size zero rather than ten will cause this test to fail one extra time in the lifetime of a list whose first operation is an "add" which would require creating the initial ten-item array, but that cost is less than the cost of creating a ten-item array that never ends up getting used.

如果使用ArrayList完成的第一个操作是向addAll传递一个包含十个以上元素的集合,那么创建一个初始十元素数组以保存ArrayList内容的任何工作都将被抛出窗口。每当有东西被添加到ArrayList时,都需要测试结果列表的大小是否超过后备存储的大小;允许初始后备存储的大小为零而不是10将导致此测试在列表的生命周期中失去一个额外的时间,该列表的第一个操作是“添加”,这将需要创建初始的十项数组,但该成本是低于创建一个永远不会被使用的十项数组的成本。

That having been said, it might have been possible to improve performance further in some contexts if there were a overload of "addAll" which specified how many items (if any) would likely be added to the list after the present one, and which could use that to influence its allocation behavior. In some cases code which adds the last few items to a list will have a pretty good idea that the list is never going to need any space beyond that. There are many situations where a list will get populated once and never modified after that. If at the point code knows that the ultimate size of a list will be 170 elements, it has 150 elements and a backing store of size 160, growing the backing store to size 320 will be unhelpful and leaving it at size 320 or trimming it to 170 will be less efficient than simply having the next allocation grow it to 170.

话虽如此,如果有一个“addAll”超载指定在当前列表之后可能会将多少项(如果有的话)添加到列表中,那么在某些情况下可能会进一步提高性能。用它来影响它的分配行为。在某些情况下,将最后几个项添加到列表中的代码将非常清楚该列表永远不需要除此之外的任何空间。在许多情况下,列表将填充一次,之后从未修改过。如果在点代码知道列表的最终大小将是170个元素,它有150个元素和大小为160的后备存储,将后备存储增加到320大小将是无益的,并将其保留为320或修改为170的效率低于简单地将下一个分配增加到170。

#4


3  

The question is 'why?'.

问题是“为什么?”。

Memory profiling inspections (for example (https://www.yourkit.com/docs/java/help/inspections_mem.jsp#sparse_arrays) shows that empty (filled with nulls) arrays occupy tons of memory .

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

Default size of 10 objects means that we allocate 10 pointers (40 or 80 bytes) for underlying array at creation and fill them in with nulls. Real java applications create millions of array lists.

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

The introduced modification removes^W postpone this memory consumption till moment you will actually use the array list.

引入的修改删除了^ W推迟了这个内存消耗,直到您实际使用数组列表为止。

#5


0  

ArrayList default size in JAVA 8 is stil 10. The only change made in JAVA 8 is that if a coder adds elements less than 10 then the remaining arraylist blank places are not specified to null. Saying so because I have myself gone through this situation and eclipse made me look into this change of JAVA 8.

JAVA 8中的ArrayList默认大小是stil 10.在JAVA 8中唯一的变化是,如果编码器添加小于10的元素,则剩余的arraylist空白位置不指定为null。这么说是因为我自己经历了这种情况并且日食使我看到了JAVA 8的这种变化。

You can justify this change by looking at below screenshot. In it you can see that ArrayList size is specified as 10 in Object[10] but the number of elements displayed are only 7. Rest null value elements are not displayed here. In JAVA 7 below screenshot is same with just a single change which is that the null value elements are also displayed for which the coder needs to write code for handling null values if he is iterating complete array list while in JAVA 8 this burden is removed from the head of coder/developer.

您可以通过查看下面的屏幕截图来证明这一变化。在其中,您可以看到在Object [10]中将ArrayList大小指定为10,但显示的元素数量仅为7.此处不显示其余的null值元素。在下面的JAVA 7中,屏幕截图与单个更改相同,即显示空值元素,如果编码器在JAVA 8中迭代完整数组列表时需要编写用于处理空值的代码,则此负担将从编码/开发人员。

Screen shot link.

屏幕截图链接。

#6


0  

After above question I gone through ArrayList Document of Java 8. I found the default size is still 10 only.

在上述问题之后,我浏览了Java 8的ArrayList Document。我发现默认大小仍然是10。

Please see below


推荐阅读
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
author-avatar
雪盈甜美
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有