Java容器ArrayList知识点总结
ArrayList
底层实现是数组,访问元素效率高(查询快,插入、修改、删除元素慢)
与LinkedList相比,它效率高,但线程不安全。
ArrayList数组是一个可变数组,可以存取包括null在内的所有元素
- 每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小
- 随着向ArrayList中不断增加元素,其容量自动增长
- 在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这样可以减少递增式再分配的数量。
- 所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多进行扩容操作而浪费时间、效率
- 源码分析
底层使用数组实现
transientObject[]elementData;
构造方法
privatestaticfinalintDEFAULT_CAPACITY=10; privatestaticfinalObject[]EMPTY_ELEMENTDATA={}; privatestaticfinalObject[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA={}; transientObject[]elementData; privateintsize; //构造一个空列表 publicArrayList(){ this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //构造一个指定初始容量的空列表 publicArrayList(intinitialCapacity){ if(initialCapacity>0){ this.elementData=newObject[initialCapacity]; }elseif(initialCapacity==0){ this.elementData=EMPTY_ELEMENTDATA; }else{ thrownewIllegalArgumentException("IllegalCapacity:"+ initialCapacity); } } //构造一个指定Collection元素的列表,这些元素按照Connection元素的迭代返回顺序进行排列 publicArrayList(Collectionc){ elementData=c.toArray(); if((size=elementData.length)!=0){ //c.toArraymight(incorrectly)notreturnObject[](see6260652) if(elementData.getClass()!=Object[].class) elementData=Arrays.copyOf(elementData,size,Object[].class); }else{ //replacewithemptyarray. this.elementData=EMPTY_ELEMENTDATA; } }
存储
//在列表的指定位置的元素用element替代,并且返回该位置原来的元素 publicEset(intindex,Eelement){ rangeCheck(index);//检查数组容量,抛出:IndexOutOfBoundsException EoldValue=elementData(index); elementData[index]=element; returnoldValue; } //在列表的尾部添加指定元素 publicbooleanadd(Ee){ ensureCapacityInternal(size+1);//数组扩容 elementData[size++]=e; returntrue; } //在列表的指定位置添加元素 publicvoidadd(intindex,Eelement){ rangeCheckForAdd(index); ensureCapacityInternal(size+1);//IncrementsmodCount!! //src:源数组,srcPro:源数组中的起始位置 //dest:目标数组,destPost:目标数组的起始位置,length:要复制的数组元素数量 //将当前位于该位置的元素以及所有后续元素后移一个位置 System.arraycopy(elementData,index,elementData,index+1, size-index); //用element替换index位置的元素 elementData[index]=element; size++; } //在列表的尾部添加Connection中的元素,元素顺序按照Connection迭代器返回的顺序 publicbooleanaddAll(Collectionc){ Object[]a=c.toArray();//转化为一个数组 intnumNew=a.length; ensureCapacityInternal(size+numNew);//IncrementsmodCount //IncrementsmodCount!! System.arraycopy(a,0,elementData,size,numNew); size+=numNew; returnnumNew!=0; } //在列表的指定位置添加Connection中的元素,元素顺序按照Connection迭代器返回的顺序 publicbooleanaddAll(intindex,Collectionc){ rangeCheckForAdd(index); Object[]a=c.toArray(); intnumNew=a.length; ensureCapacityInternal(size+numNew);//IncrementsmodCount intnumMoved=size-index; if(numMoved>0) System.arraycopy(elementData,index,elementData,index+numNew, numMoved); System.arraycopy(a,0,elementData,index,numNew); size+=numNew; returnnumNew!=0; }
读取
//移除此列表指定位置上的元素 publicEremove(intindex){ rangeCheck(index); modCount++; EoldValue=elementData(index); intnumMoved=size-index-1; if(numMoved>0) System.arraycopy(elementData,index+1,elementData,index, numMoved); elementData[--size]=null;//cleartoletGCdoitswork returnoldValue; } //移除此列表中的某个元素 publicbooleanremove(Objecto){ if(o==null){ for(intindex=0;index0) System.arraycopy(elementData,index+1,elementData,index, numMoved); elementData[--size]=null;//cleartoletGCdoitswork }
数组扩容
每当向数组中添加元素时,都需要去检查添加元素后元素的个数是否超出当前数组的长度,如果超出,数组将会进行扩容,以满足添加数据的需求。
publicvoidensureCapacity(intminCapacity){ intminExpand=(elementData!=DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ?0:DEFAULT_CAPACITY; if(minCapacity>minExpand){ ensureExplicitCapacity(minCapacity); } } privatevoidensureCapacityInternal(intminCapacity){ if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){ minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity); } ensureExplicitCapacity(minCapacity); } privatevoidensureExplicitCapacity(intminCapacity){ modCount++; //overflow-consciouscode if(minCapacity-elementData.length>0) grow(minCapacity); } privatevoidgrow(intminCapacity){ //overflow-consciouscode intoldCapacity=elementData.length; intnewCapacity=oldCapacity+(oldCapacity>>1); if(newCapacity-minCapacity<0) newCapacity=minCapacity; if(newCapacity-MAX_ARRAY_SIZE>0) newCapacity=hugeCapacity(minCapacity); //minCapacityisusuallyclosetosize,sothisisawin: elementData=Arrays.copyOf(elementData,newCapacity); } privatestaticinthugeCapacity(intminCapacity){ if(minCapacity<0)//overflow thrownewOutOfMemoryError(); return(minCapacity>MAX_ARRAY_SIZE)? Integer.MAX_VALUE: MAX_ARRAY_SIZE; }
手写ArrayList
publicclassMyArrayList/*implementsList*/{ privatetransientObject[]elementData; privateintsize;//元素个数 publicMyArrayList(){ this(10); } publicMyArrayList(intinitialCapacity){ if(initialCapacity<0){ try{ thrownewException(); }catch(Exceptione){ e.printStackTrace(); } } elementData=newObject[initialCapacity]; } publicintsize(){ returnsize; } publicbooleanisEmpty(){ returnsize==0; } //根据index删掉对象 publicvoidremove(intindex)throwsException{ rangeCheck(index); intnumMoved=size-index-1; if(numMoved>0){ System.arraycopy(elementData,index+1,elementData,index,numMoved); } elementData[--size]=null; } //删掉对象 publicbooleanremove(Objectobj)throwsException{ for(inti=0;i =size){ thrownewException(); } } //扩容 publicvoidensureCapacity(){ //数组扩容和内容拷贝 if(size==elementData.length){ //elementData=newObject[size*2+1];这么写原来数组里的内容丢失 Object[]newArray=newObject[size*2+1]; //拷贝数组里的内容 /*for(inti=0;i