【数据结构】6.java源码ArrayList

 关于ArrayList的源码关注点

1.从底层数据结构,扩容策略
2.ArrayList的增删改查
3.特殊处理重点关注
4.遍历的速度,随机访问和iterator访问效率对比
数组


1.从底层数据结构,扩容策略

对于第一个问题,底层即时一个object的数组,用来存放动态数据:
transient Object[] elementData;
默认初始容量大小是10个,注意这里有个坑不是一开始就是10个,而是当进行add操做的时候,会默认修改成10个:private static final int DEFAULT_CAPACITY = 10;数据结构


源码中进行初始化的时候:
多线程

 


而咱们的DEFAULTCAPACITY_EMPTY_ELEMENTDATA这个数据是,也就是说只进行new操做的时候,咱们是给了一个空的数组大小是0长度是0,大小是0
Private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};this

 这里源码中有一段代码:spa

 

 

 

collection.toArray()應該等同於collection.toArray(new Object[0]),返回的是Object[]類型。然而,Arrays.asList卻不是這樣,若是它的類型是一個Object[]子類(好比String[]),那麼toArray()就會返回這個子類而不是Object[],因為它調用的是clone()).net

做者:楊寒
连接:https://www.zhihu.com/question/26603565/answer/33394672
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。线程

 

EnsureCapacityInternal 扩容策略最终调用======》grow方法进行大小增加code

只有在容量不够了的时候才会采起扩容措施blog

 

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);
}

 

1.并且扩容也很简单粗暴,直接扩大1.5倍,采用右移的方式进行扩容,而后加上原始容量
2.若是括了1.5倍,仍是比须要获取的大小要小,那么就直接把大小扩为想要获取的大小
3.若是扩容以后的大小,超出限制(Integer.MAX_VALUE - 8;),那么就扩到最大Integer.MAX_VALUE,若是指望的大小还没超过这个Integer.MAX_VALUE - 8;那么就扩围Integer.MAX_VALUE - 8;索引

最后吧新的数据拷贝过来取代旧数据

 

 

2.ArrayList的增删改查


2.1 add操做

进行add操做的时候支持2种添加方式

 

 

 

 

 

添加的时候size+1,做为新的size,而后调用扩容策略
最后吧新数据放到最后一个位置,返回true


其次添加到指定位置
作了2次拷贝操做
1.先建立新的容纳大小的空间
2.而后把须要添加进去的数据的index位置,日后推移拷贝一遍,而后再指定位置写入
System.arraycopy(elementData, index, elementData, index + 1,
size - index);

 

 

 

2.2 删除remove(obj),remove(int),fastRemove

Remove(obj)删除操做底层调用的仍是fastremove
根据要删除的位置计算须要移动的元素个数

 

 

 

好比2个元素,如今要删除第一个元素,那么index=0,那么就是2-0-1 = 1;须要移动一个
Index就是对应的元素的下标,numMoved就是须要移动的元素的个数

 

 

 

 

 

直接删除索引
Remove(int)

删除这个索引以前,会先判断是否越界

 

 

和以前的删除大同小异

 

修改,查询就不说了,就是set和get操做,分别是elementData[index] = ele,和return elemenetData[index]

 

3.特殊处理重点关注,iterator

1.这里注意ArrayList有一个modCount属性,这个属性用来标识这个list被修改了多少次
2.注意使用迭代器的时候,对元素的增长或者删除,请用迭代器的删除,而不能用list的remove,并且遍历的时候只能删除,不能作新增

 


这个方法会校验

 

ExpectedModCount 而这个参数在建立iterator的时候,就进行了赋值 int expectedModCount = modCount;

 

 


4.遍历的速度,随机访问和iterator访问效率对比

并无差异,其实iterator也就是对数组访问,因此不存在效率问题,只是咱们通常的状况能够进行随机访问,而iterator只能进行遍历

 


5.是否支持多线程

这个就否了,不用管

 

 

 

借鉴:

https://www.zhihu.com/question/26603565
https://blog.csdn.net/fighterandknight/article/details/61240861

相关文章
相关标签/搜索