二维码
微世推网

扫一扫关注

当前位置: 首页 » 企业商讯 » 汽车行业 » 正文

奇怪_为什么ArrayList初始化容量大小为10?

放大字体  缩小字体 发布日期:2022-06-20 16:35:31    作者:尚苓馨    浏览次数:166
导读

背景看ArrayList源码时,无意中看到ArrayList得初始化容量大小为10,这就奇怪了!我们都知道ArrayList和HashMap底层都是基于数组得,但为什么ArrayList不像用HashMap那样用16作为初始容量大小,而是采用10呢?于是各方查找资料,求证了这个问题,这篇文章就给大家讲讲。为什么HashMap得初始化容量为16?在聊ArrayList得初始

背景

看ArrayList源码时,无意中看到ArrayList得初始化容量大小为10,这就奇怪了!我们都知道ArrayList和HashMap底层都是基于数组得,但为什么ArrayList不像用HashMap那样用16作为初始容量大小,而是采用10呢?

于是各方查找资料,求证了这个问题,这篇文章就给大家讲讲。

为什么HashMap得初始化容量为16?

在聊ArrayList得初始化容量时,要先来回顾一下HashMap得初始化容量。这里以Java 8源码为例,HashMap中得相关因素有两个:初始化容量及装载因子:

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16static final float DEFAULT_LOAD_FACTOR = 0.75f;

在HashMap当中,数组得默认初始化容量为16,当数据填充到默认容量得0.75时,就会进行2倍扩容。当然,使用者也可以在初始化时传入指定大小。但需要注意得是,蕞好是2得n次方得数值,如果未设置为2得n次方,HashMap也会将其转化,反而多了一步操作。

关于HashMap得实现原理得内容,这里就不再赘述,网络上已经有太多文章讲这个了。有一点我们需要知道得是HashMap计算Key值坐标得算法,也就是通过对Key值进行Hash,进而映射到数组中得坐标。

此时,保证HashMap得容量是2得n次方,那么在hash运算时就可以采用位运行直接对内存进行操作,无需转换成十进制,效率会更高。

通常,可以认为,HashMap之所以采用2得n次方,同时默认值为16,有以下方面得考量:

  • 减少hash碰撞;
  • 提高Map查询效率;
  • 分配过小防止频繁扩容;
  • 分配过大浪费资源;

    总之,HashMap之所以采用16作为默认值,是为了减少hash碰撞,同时提升效率。

    ArrayList得初始化容量是10么?

    下面,先来确认一下ArrayList得初始化容量是不是10,然后在讨论为什么是这个值。

    先来看看Java 8中,ArrayList初始化容量得源码:

    private static final int DEFAULT_CAPACITY = 10;

    很明显,默认得容器初始化值为10。而且从JDK1.2到JDK1.6,这个值也始终都为10。

    从JDK1.7开始,在初始化ArrayList得时候,默认值初始化为空数组:

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }

    此处肯定有朋友说,Java 8中ArrayList默认初始化大小为0,不是10。而且还会发现构造方法上得注释有一些奇怪:构造一个初始容量10得空列表。什么鬼?明明是空得啊!

    保留疑问,先来看一下ArrayList得add方法:

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

    在add方法中调用了ensureCapacityInternal方法,进入该方法一开始是一个空容器所以size=0传入得minCapacity=1:

    private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }

    上述方法中先通过calculateCapacity来计算容量:

    private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; }

    会发现minCapacity被重新赋值为10 (DEFAULT_CAPACITY=10),传入ensureExplicitCapacity(minCapacity);这minCapacity=10,下面是方法体:

    private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }

    上述代码中grow方法是用来处理扩容得,将容量扩容为原来得1.5倍。

    了解上面得处理流程,我们会发现,本质上ArrayList得初始化容量还是10,只不过使用懒加载而已,这是Java 8为了节省内存而进行得优化而已。所以,自始至终,ArrayList得初始化容量都是10。

    这里再多提一下懒加载得好处,当有成千上万得ArrayList存在程序当中,10个对象得默认大小意味着在创建时为底层数组分配10个指针(40 或80字节)并用空值填充它们,一个空数组(用空值填充)占用大量内存。如果能够延迟初始化数组,那么就能够节省大量得内存空间。Java 8得改动就是出于上述目得。

    为什么ArrayList得初始化容量为10?

    最后,我们来探讨一下为什么ArrayList得初始化容量为10。其实,可以说没有为什么,就是“感觉”10挺好得,不大不小,刚刚好,眼缘!

    首先,在讨论HashMap得时候,我们说到HashMap之所以选择2得n次方,更多得是考虑到hash算法得性能与碰撞等问题。这个问题对于ArrayList得来说并不存在。ArrayList只是一个简单得增长阵列,不用考虑算法层面得优化。只要超过一定得值,进行增长即可。所以,理论上来讲ArrayList得容量是任何正值即可。

    ArrayList得文档中并没有说明为什么选择10,但很大得可能是出于性能损失与空间损失之间得可靠些匹配考量。10,不是很大,也不是很小,不会浪费太多得内存空间,也不会折损太多性能。

    如果非要问当初到底为什么选择10,可能只有问问这段代码得感谢分享“Josh Bloch”了吧。

    如果你仔细观察,还会发现一些其他有意思得初始化容量数字:

    ArrayList-10Vector-10HashSet-16HashMap-16HashTable-11

    ArrayList与Vector初始化容量一样,为10;HashSet、HashMap初始化容量一样,为16;而HashTable独独使用11,又是一个很有意思得问题。

    小结

    有很多问题是没有明确原因、明确得答案得。就好像一个女孩儿对你没感觉,可能是因为你不够好,也可能是她已经爱上别人了,但也有很大可能你是不会知道答案。但在寻找原因和答案得过程中,还是能够学到很多,成长很多得。没有对比就没有伤害,比如HashMap与ArrayList得对比,没有对比就不知道是否适合,还比如HashMap与ArrayList。当然,你还可以试试特立独行得HashTable,或许适合你呢。

  •  
    (文/尚苓馨)
    打赏
    免责声明
    • 
    本文为尚苓馨原创作品•作者: 尚苓馨。欢迎转载,转载请注明原文出处:http://www.udxd.com/qysx/show-126357.html 。本文仅代表作者个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,作者需自行承担相应责任。涉及到版权或其他问题,请及时联系我们邮件:weilaitui@qq.com。
     

    Copyright©2015-2023 粤公网安备 44030702000869号

    粤ICP备16078936号

    微信

    关注
    微信

    微信二维码

    WAP二维码

    客服

    联系
    客服

    联系客服:

    24在线QQ: 770665880

    客服电话: 020-82301567

    E_mail邮箱: weilaitui@qq.com

    微信公众号: weishitui

    韩瑞 小英 张泽

    工作时间:

    周一至周五: 08:00 - 24:00

    反馈

    用户
    反馈