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

ArrayList8源码分析

时间:2023-04-02 00:29:19 Java

ArrayList8源码分析1.简介-集合底层是一个Object[]的数组,内部实现了动态扩展-是内存中连续的内存空间,有序存储,所以在搜索某个A位置的时候数据很快,中间插入数据很慢。-允许空值,值完全可重复,但必须是同一类型。-初始大小为10,但后续扩容涉及到复制数组,浪费系统能量。如果已知数据量,最好指定集合的??大小。2.实现的接口(1)RandomAcess接口允许通用算法改变它们的行为以在应用于随机或顺序访问列表时提供良好的性能。(2)Cloneable接口集合可以实现接口和数据的克隆。(3)Serializable接口集支持序列化,可用于网络传输。3、属性1,privatestaticfinalintDEFAULT_CAPACITY=10;//表示集合数组默认大小为102,privatestaticfinalObject[]EMPTY_ELEMENTDATA={};//空数组,当设置大小为0时,使用3,privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};//默认空参构造函数使用4、transientObject[]elementData;数组值5,私有int大小;当前数组的大小,即数组包含的元素个数4.构造方法(1)无参构造方法publicArrayList(){//等价于elementData={}this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}(2)指定初始大小的构造方法publicArrayList(intinitialCapacity){if(initialCapacity>0){//当初始化大小大于0时,则直接赋值this.elementData=newObject[initialCapacity];}elseif(initialCapacity==0){//当初始化大小等于0时,=={}this.elementData=EMPTY_ELEMENTDATA;}else{//否则参数错误thrownewIllegalArgumentException("IllegalCapacity:"+initialCapacity);}}(3)引入另一种集合构造方法publicArrayList(Collectionc){elementData=c.toArray();if((size=elementData.length)!=0){//c.toArray可能(错误地)不返回Object[](参见6260652)if(elementData.getClass()!=Object[].class)elementData=Arrays.copyOf(elementData,size,Object[].class);}else{//替换为空数组。this.elementData=EMPTY_ELEMENTDATA;}}5。执行添加操作(1)一般添加数据publicbooleanadd(Ee){//先将当前数组的大小加1,然后判断是否需要扩容ensureCapacityInternal(size+1);//递增modCount!!//填充数组末尾的值elementData[size++]=e;返回真;}(2)向指定位置添加数据publicvoidadd(intindex,Eelement){//该方法用于判断添加的位置是否越界(合理的位置应该是:0)rangeCheckForAdd(指数);//先+1当前数组的大小,再判断是否需要扩容ensureCapacityInternal(size+1);////索引位置后数据移回System.array复制(元素数据,索引,元素数据,索引+1,大小-索引);//移动后,index还是旧值,然后新值直接覆盖elementData[index]=element;//长度加1size++;}(3)扩容操作//方法一:扩容入口privatevoidensureCapacityInternal(intminCapacity){ensureExplicitCapacity(calculateCapacity(elementData,minCapacity));}//查看当前数组大小,如果是第一次保存,直接返回初始值10privatestaticintcalculateCapacity(Object[]elementData,intminCapacity){//判断是否为空集合,如果数组第一次没有,默认值10和当前数(当前数据长度大小+1)if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){//第一次返回10returnMath.max(DEFAULT_CAPACITY,最小容量);}//如果当前数组不为空,直接返回当前数组length+1returnminCapacity;}//方法二:privatevoidensureExplicitCapacity(intminCapacity){modCount++;//数据操作的个数+1/??/size加1后的值与数组总长度比较,如果数组加1后的个数大于总长度,需要扩容if(minCapa城市-elementData.length>0)grow(minCapacity);}//方法三:扩容privatevoidgrow(intminCapacity){//先获取旧数组的总长度,比如10intoldCapacity=elementData.length;//新长度=旧长度+旧长度/2(即:新=旧*1.5)intnewCapacity=oldCapacity+(oldCapacity>>1);//如果扩展1.5倍后该值小于size+1if(newCapacity-minCapacity<0)//newlength=size+1newCapacity=minCapacity;//新长度是否大于Integer.MAX_VALUE-8?if(newCapacity-MAX_ARRAY_SIZE>0)//当扩容到最大值(int.Max-8)时,返回int的最大值,表示容量不能再扩容newCapacity=hugeCapacity(minCapacity);//创建新数组后,再实现数据复制elementData=Arrays.copyOf(elementData,newCapacity);}通过这个过程,你应该明白了,在创建列表的时候,尽量指定集合的??大小,避免频繁扩容。6.执行删除操作(1)根据下标删除publicEremove(intindex){//判断下标是否符合标准rangeCheck(index);模数++;//获取旧值,删除成功后返回EoldValue=elementData(index);//获取需要移动的元素个数(数组元素个数-当前位置)intnumMoved=size-index-1;if(numMoved>0)//将当前位置后一位移动到数组的最后一位统一向前移动一位,当前位置的元素被索引+1的元素覆盖。System.arraycopy(elementData,index+1,elementData,index,numMoved);//清空数组的最后一个位置elementData[--size]=null;返回旧值;}注意:这个操作没有遍历数组,所以复杂度为o(1(2)根据内容删除publicbooleanremove(Objecto){//如果传入空值,则数组中的空值将被删除if(o==null){for(intindex=0;index0)//从当前位置向前移动一位到数组的最后一位,当前位置的元素将被索引+1的元素覆盖。System.arraycopy(elementData,index+1,elementData,index,numMoved);元素数据[--大小]=空;//明确让GC干活}(4)DeleteListlistinlooptraversallist=newArrayList<>();列表.添加(3);列表.添加(5);列表.添加(9);list.add(0,999);System.out.println(列表);for(Integernum:list){if(num==9){list.remove(num);//会报错:java.util.ConcurrentModificationException}}结果:上述代码之所以报错是因为在遍历之前,当前集合的操作数已经赋值给了预期操作数的一个变量,而它remove之前会执行当前操作指令数+1,然后将当前操作数与预期操作数进行比较。如果不一致,就会报上面的错误。总之,在改变集合之前必须先修改当前操作数。那么:如何正确删除集合中的元素呢?Listlist=newArrayList<>();列表.添加(3);列表.添加(5);列表.添加(9);list.add(0,999);System.out.println(列表);//首先把集合变成一个迭代器Iteratoriterator=list.iterator();while(iterator.hasNext()){整数num=iterator.next();if(num==5){iterator.remove();}}System.out.println(list);7查询操作publicEget(intindex){//检查索引大小是否足够合理(0<=x<=size)rangeCheck(index);//注解returnelementData[index]的值returnelementData(index);}8集合被清除publicvoidclear(){modCount++;//循环删除所有元素for(inti=0;i