栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

ArrayList底层原理

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ArrayList底层原理

ArrayList底层原理

ArrayList在工作中经常用到,今天来看一下ArrayList的底层是如何实现的?在这之前,先抛出几个问题。

1.ArrayList底层实现的数据结构是什么?

2.ArrayList的初始化容量是多少,底层的扩容机制是什么?

3.ArrayList是在什么时候初始化容量的?

4.ArrayList是如何实现添加元素操作的?

//实现了List接口,实现了List的常用方法,如add(E e)
//实现了RandomAccess接口,这是个标记接口,接口中没有任何方法,作用只是标记ArrayList可以支持快速随机访问
//实现了Cloneable接口,表示ArrayList实例调用clone()可以克隆一个和自己一样的实例(这里是浅拷贝)。
//实现了Serializable接口,表示可以序列化和反序列化,可以在网络中传输。
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;
    //默认容量是10
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //底层使用Object数组实现的,所有可以存任何类型
    transient Object[] elementData;  
    private int size;
    //代码太多,省略......
}
下面代码是ArrayList添加一个元素的底层实现

这两行代码,底层帮我们做了什么?debug进去看看

ArrayList arrayList = new ArrayList<>();
arrayList.add(new String("I am xiao qiang"));

首先是类加载器,他的作用是将class文件加载到jvm虚拟机中

接着进入到了ArrayList的构造方法中,可以看到构造方法给elementData赋了一个空值,说明此时仅仅创建一个ArrayList对象,除此之外没有做任何事情。

这也说明,我们只是创建了ArrayList对象,它并没有初始化容量。

接下来dubug进入到了add()方法中

进入到String的构造方法中,创建出String字符串对象,并赋值“I am xiao qiang”

继续debug,终于执行了ArrayList的add()方法,ensureCapacityInternal是判断是否要扩容的方法,进入该方法

可以看到底层是调用了一个计算容量的方法calculateCapacity,然后将默认容量10返回了,这说明ArrayList容量的初始化是在添加元素add()方法后进行的

接着继续执行add()方法,elementData[0]被赋值成"I am xiao qiang"

到此,两行代码终于结束了。

下面我们看一下ArrayList扩容机制的代码。

如果minCapacity的值大于add数据之前的大小,就调用grow方法,进行扩容,否则什么也不做。

下面是具体看出来扩容机制的大小增长规则了:

private void grow(int minCapacity) {  
       // overflow-conscious code  
       int oldCapacity = elementData.length;  
    //oldCapacity >> 1就是1/2 oldCapacity
       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);  
   }  

注意:这里传过来的minCapcatiy的值是size+1,能够实现grow方法调用就肯定是(size+1)>elementData.length的情况,所以size就是初始最大容量或上一次扩容后达到的最大容量,所以才会进行扩容。newCapacity=oldCapacity+(oldCapacity>>1),这里就是扩容大小确定的地方,相当于新的最大容量是 size+1+size/2 相当于原来的1.5倍然后加1
最新大厂IT课程:点击获取

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/985218.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号