当前位置: 首页 > 后端技术 > Java

JavaArrayList

时间:2023-04-01 19:02:52 Java

JavaArrayList属性/***默认初始容量。**如果初始化时未指定,则默认容量为10*/privatestaticfinalintDEFAULT_CAPACITY=10;/***共享空数组实例用于空实例。*/privatestaticfinalObject[]EMPTY_ELEMENTDATA={};/***用于默认大小的空实例的共享空数组实例。我们*将此与EMPTY_ELEMENTDATA区分开来,以了解在添加第一个元素时要膨胀多少。*/privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};/***存储ArrayList元素的数组缓冲区。*ArrayList的容量就是这个数组缓冲区的长度。任何*elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA*的空ArrayList*将在添加第一个元素时扩展为DEFAULT_CAPACITY。**使用来存储所有元素*/transientObject[]elementData;//非私有以简化嵌套类访问/***ArrayList的大小(它包含的元素数)。**@serial*当前elementData已有元素的长度,新元素会放在elementData[size]*/privateintsize下;constructordefaultconstructor/***构造一个初始容量为十的空列表。*/publicArrayList(){this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}指定长度/***构造一个具有指定初始容量的空列表。**@paraminitialCapacity列表的初始容量*@throwsIllegalArgumentException如果指定的初始容量*为负数*/publicArrayList(intinitialCapacity){if(initialCapacity>0){//创建一个长度为initialCapacity的新数组this.elementData=newObject[初始容量];}elseif(initialCapacity==0){this.elementData=EMPTY_ELEMENTDATA;}else{thrownewIllegalArgumentException("非法容量:"+initialCapacity);}}Incomingcollection/***构造一个包含指定集合元素的列表,按照它们由t返回的顺序他集合的*迭代器。**@paramc其元素要放入此列表中的集合*@throwsNullPointerException如果指定的集合为空*/publicArrayList(Collectionc){elementData=c.toArray();//如果传入集合的长度不为0,则将集合中的元素复制到elementDataif((size=elementData.length)!=0){//防止c.toArray(错误地)不返回Object[]//(参见例如https://bugs.openjdk.java.net/browse/JDK-6260652)if(elementData.getClass()!=Object[].class)elementData=Arrays.copyOf(elementData,size,Object[]。班级);}else{//替换为空数组。this.elementData=EMPTY_ELEMENTDATA;}}扩容最大长度根据注释可以看出,有些虚拟机需要在数组中保存额外的信息(savedextraInformation)需要占用一定的空间,所以ArrayList的最大长度为2^32-8/***要分配的数组的最大大小(除非必要)。*一些虚拟机在数组中保留了一些头字。*尝试分配更大的数组可能会导致*OutOfMemoryError:请求的数组大小超过VM限制*/privatestaticfinalintMAX_ARRAY_SIZE=Integer.MAX_VALUE-8;每次扩容,newCapacity为oldCapacity+(oldCapacity>>1),相当于旧容量的1.5倍/***返回一个至少和给定的最小容量一样大的容量。*如果足够,返回当前容量增加50%。*不会返回大于MAX_ARRAY_SIZE的容量,除非*给定的最小容量大于MAX_ARRAY*param。minCapacity所需的最小容量*@throwsOutOfMemoryErrorifminCapacity小于零*/privateintnewCapacity(intminCapacity){//溢出意识代码intoldCapacity=elementData.length;intnewCapacity=oldCapacity+(oldCapacity>>1);//根据扩容规则计算出的新容量小于预期容量if(newCapacity-minCapacity<=0){//使用默认构造函数初始化时,这里初始化底层数组//的长度新的底层数组是默认容量(10)和预期容量之间的最大值if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA)返回Math.max(DEFAULT_CAPACITY,minCapacity);if(minCapacity<0)//溢出抛出newOutOfMemoryError();返回最小容量;}//根据扩容规则计算的容量是否超过了默认的最大容量?//不超过:直接返回//超过:根据hugeCapacity()计算新的长度return(newCapacity-MAX_ARRAY_SIZE<=0)?newCapacity:hugeCapacity(minCapacity);}当通过默认规则扩展到原来的1.5时,如果超过了默认最大容量时,通过比较预期容量和默认最大容量来判断最大容量;当预期容量大于默认的MAX_ARRAY_SIZE时,返回Integer.MAX_VALUE;否则,它返回默认的MAX_ARRAY_SIZEprivatestaticinthugeCapacity(intminCapacity){if(minCapacity<0)//overflowthrownewOutOfMemoryError();返回(最小容量>MAX_ARRAY_SIZE)?Integer.MAX_VALUE:MAX_ARRAY_SIZE;}/***增加容量以确保它至少可以容纳*最小容量参数指定的元素数量。**@paramminCapacity所需的最小容量*@throwsOutOfMemoryError如果minCapacity小于零*/privateObject[]grow(intminCapacity){returnelementData=Arrays.copyOf(elementData,newCapacity(minCapacity));}privateObject[]grow(){returngrow(size+1);}add()一共有ofadd方法两个public方法,一个是add(Ee)在末尾添加一个元素,一个是add(intindex,Eelement)在任意位置插入一个元素。在末尾插入add(Ee)。公共方法调用add(Ee,Object[]elementData,ints)/***将指定的元素追加到此列表的末尾。**@parame元素要附加到这个列表*@return{@codetrue}(由{@linkCollection#add}指定)*/publicbooleanadd(Ee){modCount++;添加(e,元素数据,大小);returntrue;}如果当前容量已满,则扩大容量,否则直接将元素放到s(=size)位置,数组元素长度size+1/***这个helper方法从add(E)split出来,用来保持方法*字节码大小小于35(-XX:MaxInlineSize默认值),*这有助于在C1编译循环中调用add(E)。*/privatevoidadd(Ee,Object[]elementData,ints){if(s==elementData.length)elementData=grow();元素数据[s]=e;size=s+1;}insertatanypositionadd(intindex,Eelement)/***在此列表中的指定位置插入指定元素。将当前位于该位置的元素(如果有)和*任何后续元素向右移动(将其索引加一)。**@paramindex指定元素要插入的索引*@paramelement要插入的元素*@throwsIndexOutOfBoundsException{@inheritDoc}*/publicvoidadd(intindex,Eelement){//检查位置是否待插入越界//检查的范围是[0,size]rangeCheckForAdd(index);模数++;最终诠释;对象[]元素数据;//数组已满,需要扩容if((s=size)==(elementData=this.elementData).length)elementData=grow();//复制原始元素到新数组System.arraycopy(elementData,index,elementData,index+1,s-index);元素数据[索引]=元素;size=s+1;}remove()publicEremove(intindex)和publicbooleanremove(Objecto)方法的底层依赖于fastRemove(Object[]es,inti)方法。底层原理是将待删除元素的索引i之后的元素复制到i开始的位置,直接复制待删除元素Override/***privateremove方法,跳过边界检查,不*返回删除的值。*/privatevoidfastRemove(Object[]es,inti){modCount++;最终诠释新尺寸;if((newSize=size-1)>i)//更新当前元素个数//从位置i+1复制到从i开始的位置,并覆盖i处的元素System.arraycopy(es,i+1,es,i,newSize-i);es[size=newSize]=null;}