javaArrayList 源码解析文档格式.docx
- 文档编号:17285892
- 上传时间:2022-11-30
- 格式:DOCX
- 页数:13
- 大小:21.52KB
javaArrayList 源码解析文档格式.docx
《javaArrayList 源码解析文档格式.docx》由会员分享,可在线阅读,更多相关《javaArrayList 源码解析文档格式.docx(13页珍藏版)》请在冰豆网上搜索。
//把数组的长度赋值给ArrayList的size属性
size=elementData.length;
//c.toArraymight(incorrectly)notreturnObject[](see6260652)
if(elementData.getClass()!
=Object[].class)
elementData=Arrays.copyOf(elementData,size,Object[].class);
第一个构造方法使用提供的initialCapacity来初始化elementDate数组的大小,第二个构造方法调用构造方法并传入参数10,也就是默认elementData数组的大小为10.第三个构造方法将提供的集合转成数组返回给elementData(返回若不是Object[]就调用Aeeays.copyOf()将其转为Object[])。
C、ArrayList的动态扩容:
oldcapa*1.5
privatestaticfinalintDEFAULT_CAPACITY=10;
以add方法为入口
publicbooleanadd(Ee){
ensureCapacityInternal(size+1);
//IncrementsmodCount!
!
elementData[size++]=e;
returntrue;
可见,在添加元素之前,会先调用ensureCapacityInternal这个方法,那就再进到这个这个方法中去。
privatevoidensureCapacityInternal(intminCapacity){
if(elementData==EMPTY_ELEMENTDATA){
minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity);
ensureExplicitCapacity(minCapacity);
首先,看看数组是否为空,如果是,就将DEFAULT_CAPACITY和minCapacity的较大的一个作为初始大小赋值给minCapacity
,DEFAULT_CAPACITY是10,minCapacity就是add方法中传入的size+1。
如果数组不为空,就直接执行ensureExplicitCapacity方法。
ensureExplicitCapacity方法的实现如下:
privatevoidensureExplicitCapacity(intminCapacity){
modCount++;
//overflow-consciouscode
if(minCapacity-elementData.length>
grow(minCapacity);
在这个方法里,会比较minCapacity与elementData.length的大小。
当第一次插入值时,由于minCapacity一定大于等于10,而elementData.length是0,所以会去继续执行grow方法,那就继续进入到这个方法中去。
grow方法的实现如下:
Privatevoidgrow(intminCapacity){
intoldCapacity=elementData.length;
intnewCapacity=oldCapacity+(oldCapacity>
>
1);
if(newCapacity-minCapacity<
newCapacity=minCapacity;
if(newCapacity-MAX_ARRAY_SIZE>
newCapacity=hugeCapacity(minCapacity);
//minCapacityisusuallyclosetosize,sothisisawin:
elementData=Arrays.copyOf(elementData,newCapacity);
这个方法首先计算出一个容量,大小为oldCapacity+(oldCapacity>
1)。
即elementData数组长度的1.5倍。
再从minCapacity和
这个容量中取较大的值作为扩容后的新的数组的大小。
这时,会出现两种情况:
1)新的容量小于数组的最大值MAX_ARRAY_SIZE,即
privatestaticfinalintMAX_ARRAY_SIZE=Integer.MAX_VALUE-8;
最大的容量之所以设为Integer.MAX_VALUE-8,在定义上方的注释中已经说了,大概是一些JVM实现时,会在数组的前面放一些额外的数据,再加上数组中的数据大小,有可能超过一次能申请的整块内存的大小上限,所以会出现OutOfMemoryError。
2)新的容量大于数组的最大值MAX_ARRAY_SIZE
这时,又会进入另一个方法hugeCapacity()
privatestaticinthugeCapacity(intminCapacity){
if(minCapacity<
0)//overflow
thrownewOutOfMemoryError();
return(minCapacity>
MAX_ARRAY_SIZE)?
Integer.MAX_VALUE:
MAX_ARRAY_SIZE;
会对minCapacity和MAX_ARRAY_SIZE进行比较,minCapacity大的话,就将Integer.MAX_VALUE作为新数组的大小,否则将MAX_ARRAY_SIZE作为数组的大小。
最后,就把原来数组的数据复制到新的数组中。
调用了Arrays的copyOf方法。
内部是System的arraycopy方法,由于是native方法,所以效率较高。
二、ArrayList的其他方法
add(Ee)
add(Ee)都知道是在尾部添加一个元素,如何实现的呢?
1.public
boolean
add(E
e)
{
2.
ensureCapacity(size
+
1);
//
Increments
modCount!
3.
elementData[size++]
=
e;
4.
return
true;
5.
}
都说ArrayList是基于数组实现的,属性中也看到了数组,具体是怎么实现的呢?
比如就这个添加元素的方法,如果数组大,则在将某个位置的值设置为指定元素即可,如果数组容量不够了呢?
看到add(Ee)中先调用了ensureCapacity(size+1)方法,之后将元素的索引赋给elementData[size],而后size自增。
例如初次添加时,size为0,add将elementData[0]赋值为e,然后size设置为1(类似执行以下两条语句elementData[0]=e;
size=1)。
将元素的索引赋给elementData[size]不是会出现数组越界的情况吗?
这里关键就在ensureCapacity(size+1)中了。
根据ensureCapacity的方法名可以知道是确保容量用的。
ensureCapacity(size+1)后面的注释可以明白是增加modCount的值(加了俩感叹号,应该蛮重要的,来看看)。
1./**
*
Increases
the
capacity
of
this
<
tt>
ArrayList<
/tt>
instance,
if
necessary,
to
ensure
that
it
can
hold
at
least
number
elements
specified
by
minimum
argument.
6.
@param
minCapacity
desired
7.
*/
8.
public
void
ensureCapacity(int
minCapacity)
9.
modCount++;
10.
int
oldCapacity
elementData.length;
11.
(minCapacity
oldCapacity)
12.
Object
oldData[]
elementData;
13.
newCapacity
(oldCapacity
3)/2
1;
14.
(newCapacity
15.
minCapacity;
16.
is
usually
close
size,
so
a
win:
17.
elementData
Arrays.copyOf(elementData,
newCapacity);
18.
19.
这是对modCount的解释,意为记录list结构被改变的次数(观察源码可以发现每次调用ensureCapacoty方法,modCount的值都将增加,但未必数组结构会改变,所以感觉对modCount的解释不是很到位)。
增加modCount之后,判断minCapacity(即size+1)是否大于oldCapacity(即elementData.length),若大于,则调整容量为max((oldCapacity*3)/2+1,minCapacity),调整elementData容量为新的容量,即将返回一个内容为原数组元素,大小为新容量的数组赋给elementData;
否则不做操作。
所以调用ensureCapacity至少将elementData的容量增加的1,所以elementData[size]不会出现越界的情况。
容量的拓展将导致数组元素的复制,多次拓展容量将执行多次整个数组内容的复制。
若提前能大致判断list的长度,调用ensureCapacity调整容量,将有效的提高运行速度。
可以理解提前分配好空间可以提高运行速度,但是测试发现提高的并不是很大,而且若list原本数据量就不会很大效果将更不明显。
add(intindex,Eelement)在指定位置插入元素。
add(int
index,
E
element)
(index
size
||
index
0)
throw
new
IndexOutOfBoundsException(
"
Index:
+index+"
Size:
+size);
ensureCapacity(size+1);
System.arraycopy(elementData,
elementData,
1,
-
index);
elementData[index]
element;
size++;
首先判断指定位置index是否超出elementData的界限,之后调用ensureCapacity调整容量(若容量足够则不会拓展),调用System.arraycopy将elementData从index开始的size-index个元素复制到index+1至size+1的位置(即index开始的元素都向后移动一个位置),然后将index位置的值指向element。
addAll(Collection<
c)
addAll(Collection<
extends
E>
c)
Object[]
c.toArray();
numNew
a.length;
numNew);
modCount
System.arraycopy(a,
0,
+=
numNew;
0;
先将集合c转换成数组,根据转换后数组的程度和ArrayList的size拓展容量,之后调用System.arraycopy方法复制元素到elementData的尾部,调整size。
根据返回的内容分析,只要集合c的大小不为空,即转换后的数组长度不为0则返回true。
addAll(intindex,Collection<
addAll(int
Collection<
size);
numMoved
index;
(numMoved
numNew,
numMoved);
先判断index是否越界。
其他内容与addAll(Collection<
c)基本一致,只是复制的时候先将index开始的元素向后移动X(c转为数组后的长度)个位置(也是一个复制的过程),之后将数组内容复制到elementData的index位置至index+X。
clear()
clear()
Let
gc
do
its
work
for
(int
i
size;
i++)
elementData[i]
null;
clear的时候并没有修改elementData的长度(好不容易申请、拓展来的,凭什么释放,留着搞不好还有用呢。
这使得确定不再修改list内容之后最好调用trimToSize来释放掉一些空间),只是将所有元素置为null,size设置为0。
clone()
返回此ArrayList实例的浅表副本。
(不复制这些元素本身。
)
clone()
try
v
(ArrayList<
)
super.clone();
v.elementData
v.modCount
v;
catch
(CloneNotSupportedException
shouldn'
t
happen,
since
we
are
Cloneable
InternalError();
调用父类的clone方法返回一个对象的副本,将返回对象的elementData数组的内容赋值为原对象elementData数组的内容,将副本的modCount设置为0。
contains(Object)
contains(Object
o)
indexOf(o)
indexOf方法返回值与0比较来判断对象是否在list中。
接着看indexOf。
indexOf(Object)
indexOf(Object
(o
==
null)
(elementData[i]==null)
i;
else
(o.equals(elementData[i]))
-1;
通过遍历elementData数组来判断对象是否在list中,若存在,返回index([0,size-1]),若不存在则返回-1。
所以contains方法可以通过indexOf(Object)方法的返回值来判断对象是否被包含在list中。
既然看了indexOf(Object)方法,接着就看lastIndexOf,光看名字应该就明白了返回的是传入对象在elementData数组中最后出现的index值。
lastIndexOf(Object
size-1;
i--)
采用了从后向前遍历element数组,若遇到Objec
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- javaArrayList 源码解析 源码 解析
![提示](https://static.bdocx.com/images/bang_tan.gif)