分析一个源码都是从它的最常用的方法入手
ArrayList arrayList =new ArrayList();泛型这里先不讲,之后另开一篇文章解释泛型
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData =DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[]elementData
可以知道,new ArrayList();新建了一个空数组,之后在调用add()方法添加第一个元素的时候会设置默认大小为10
我们再来看看add()方法
arrayList.add(new Object());
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size +1); // Increments modCount!!
elementData[size++] = e;
return true;
}
里面有2个方法
第一个方法是用来判断是否是初始创建的空数组,如果是的话就计算最少需要的大小和默认最小为10的大小进行比较得出一个两者比较大的值,当然add()方法只会导致size+1,但是还有一个addAll()方法,所以第一次 add()大小就是10,addAll()就是10或者要添加元素的大小中的教大者
private void ensureCapacityInternal(int minCapacity) {
if (elementData ==DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
计算出要初始化的大小后进行扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity -elementData.length >0)
grow(minCapacity);
}
先对容量溢出做一个判断,再去扩容
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
//记录扩容前的数组长度
int oldCapacity =elementData.length;
记算新的容量,规则是旧容量*3
int newCapacity = oldCapacity + (oldCapacity >>1);
//比较计算容量是否小于刚刚比较得出的最小容量
if (newCapacity - minCapacity <0)
newCapacity = minCapacity;
if (newCapacity -MAX_ARRAY_SIZE >0)
newCapacity =hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//关键,复制了旧数组到新容量的数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
//就是判断了下上限和下限容量
private static int hugeCapacity(int minCapacity) {
if (minCapacity <0)// overflow
throw new OutOfMemoryError();
return (minCapacity >MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
第二个方法indexOf(Object o)这个方法就是for循环遍历数组,先判null如果是null就不能通过equals比较,直接判断元素是否为null,然后通过equals比较元素,找到就返回数组下标,没找到返回-1
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o ==null) {
for (int i =0; i
if (elementData[i]==null)
return i;
}else {
for (int i =0; i
if (o.equals(elementData[i]))
return i;
}
return -1;
}
第三个方法lastIndexOf(Object o) 这个跟上面的一样,只是倒序遍历
get set当然就是通过数组下标来获取/设置元素
最后是add(int index, E element)
public void add(int index, E element) {
if (index >size || index <0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
ensureCapacityInternal(size +1); // Increments modCount!!
//扩容生成新数组后把数组0到index复制 index+1 到size-index复制,然后把要加入的元素放在index位置上
System.arraycopy(elementData, index, elementData, index +1,
size - index);
elementData[index] = element;
size++;
}
这个remove(Object o)方法比较简单,就是先找到要移除的元素,找到就移除(顺序遍历,所以是移除第一个找到的元素)
public boolean remove(Object o) {
if (o ==null) {
for (int index =0; index
if (elementData[index] ==null) {
fastRemove(index);
return true;
}
}else {
for (int index =0; index
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved =size - index -1;
if (numMoved >0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] =null; // clear to let GC do its work
}
public E remove(int index) {
if (index >=size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
modCount++;
E oldValue = (E)elementData[index];
int numMoved =size - index -1;
if (numMoved >0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] =null; // clear to let GC do its work
return oldValue;
}
下面分析一些不常用的方法