ArrayList源码学习
1. ArrayList参数及其含义存储对象元素transientObject[]elementData;元素的个数privateintsize;2. 常用方法get()方法publicEget(intindex){rangeCheck(index);returnelementData(index);}get方法传一个index参数表示获取指定下标的元素。get方法内首先进行rangCheck范围检查。然后返回下标对应的元素。privatevoidrangeCheck(intindex){if(indexsize)thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));}rangCheck判断要获取的数据索引是否大于等于arrayList的长度。大于等于就抛异常。EelementData(intindex){return(E)elementData[index];}从数组中获取元素并转换为指定类型返回。2. set方法publicEset(intindex,Eelement){rangeCheck(index);EoldValueelementData(index);elementData[index]element;returnoldValue;}set方法首先校验要修改的元素位置校验同上如果校验通过访问数组中下标对应的元素然后修改他的值并返回修改前的值。3. add方法publicbooleanadd(Ee){ensureCapacityInternal(size1);// Increments modCount!!elementData[size]e;returntrue;}ensureCapacityInternal(size 1);第一行确保元素个数不会超过数组长度。elementData[size] e;在末尾添加元素并且修改size的大小。privatevoidensureCapacityInternal(intminCapacity){ensureExplicitCapacity(calculateCapacity(elementData,minCapacity));}ensureCapacityInternal方法首先调用calculateCapacity计算容量。然后调用ensureExplicitCapacity确保数组长度可以容纳下这么多的元素。privatevoidensureExplicitCapacity(intminCapacity){modCount;// overflow-conscious codeif(minCapacity-elementData.length0)grow(minCapacity);}minCapacity - elementData.length 0数组中元素个数大于数组长度。需要扩容调用grow方法进行扩容。privatevoidgrow(intminCapacity){// overflow-conscious codeintoldCapacityelementData.length;intnewCapacityoldCapacity(oldCapacity1);if(newCapacity-minCapacity0)newCapacityminCapacity;if(newCapacity-MAX_ARRAY_SIZE0)newCapacityhugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementDataArrays.copyOf(elementData,newCapacity);}扩容后新的数组容量为旧数组容量的1.5倍oldCapacity (oldCapacity 1)。如果扩容后的数组容量减去元素个数大于0说明扩容不够。让新的数组容量等于元素个数。if (newCapacity - MAX_ARRAY_SIZE 0)然后判断新的数组容量是否大于最大的数组大小大于的话需要调用hugeCapacity获取最大的数组长度。Arrays.copyOf(elementData, newCapacity);将旧的数组复制到新的数组中新数组的容量为上面计算所得。indexOf方法publicintindexOf(Objecto){if(onull){for(inti0;isize;i)if(elementData[i]null)returni;}else{for(inti0;isize;i)if(o.equals(elementData[i]))returni;}return-1;}根据查找的元素分了两种情况。一种要查的元素为空遍历数组找到为空的元素返回下标。一种要查的元素不为空遍历数组找到相同的元素返回下标。否则返回-1。remove方法publicbooleanremove(Objecto){if(onull){for(intindex0;indexsize;index)if(elementData[index]null){fastRemove(index);returntrue;}}else{for(intindex0;indexsize;index)if(o.equals(elementData[index])){fastRemove(index);returntrue;}}returnfalse;}根据要删除的元素分了两种情况一种是删除空元素一种是非空元素。对于空元素遍历数组如果元素为空调用fastRemove进行元素的删除。对于非空元素遍历数组如果元素与要删除的元素相同调用fastRemove方法删除元素。删除成功返回true否则返回false。privatevoidfastRemove(intindex){modCount;intnumMovedsize-index-1;if(numMoved0)System.arraycopy(elementData,index1,elementData,index,numMoved);elementData[--size]null;// clear to let GC do its work}int numMoved size - index - 1;首先计算要移动的元素个数。要移动的元素个数为要删除元素之后的所有元素不包括被删除元素。如果要删除的元素大于0则调用System.arraycopy方法进行数据的移动对于源数组和目标数组相同的情况该方法会首先将index1到index1numMoved结果为数组结尾比如对于下标为0123的数组删除下标为1的元素该处计算后的值为11112的值复制到一个临时数组然后将临时数组的值复制到index到indexnumMoved的位置。elementData[--size] null;将最后一个元素赋值为空同时修改元素个数为size-1。