先来比较一下两者add(Object obj)的源码实现区别:
ArrayList:
当new一个ArrayList的时候,会调用其构造方法创建一个Object elementData[],用来存放数据,而EMPTY_ELEMENTDATA则是:final Object EMPTY_ELEMENTDATA[] = new Object[0];
public ArrayList()
{
elementData = EMPTY_ELEMENTDATA;
}
添加一个数据时,先调用ensureCapacityInternal(int i)方法对当前数组进行扩容,详细代码如下:
private void ensureCapacityInternal(int i)
{
if(elementData == EMPTY_ELEMENTDATA)
i = Math.max(10, i);
ensureExplicitCapacity(i);
}
private void ensureExplicitCapacity(int i)
{
modCount++;
if(i - elementData.length > 0)
grow(i);
}
private void grow(int i)
{
int j = elementData.length;
int k = j + (j >> 1);
if(k - i < 0)
k = i;
if(k - 2147483639 > 0)
k = hugeCapacity(i);
elementData = Arrays.copyOf(elementData, k);
}
添加当前对象
public boolean add(Object obj)
{
ensureCapacityInternal(size + 1);//添加数据前先进行扩容
elementData[size++] = obj;//把当前需要添加的对象放在数组的的最后一个位置
eturn true;
}
LinkedList:
当new一个LinkedList时,调用构造方法进行初始化,把size设为0;
public LinkedList()
{
size = 0;
}
添加数据
public boolean add(Object obj)
{
linkLast(obj);
return true;
}
//linkLast方法为把传入该方法的Object对象放在链表的最后一个位置
void linkLast(Object obj)
{
Node node1 = last;
Node node2 = new Node(node1, obj, null);//调用Node的构造方法,把obj变成Node对象
last = node2;
if(node1 == null)
first = node2;
else
node1.next = node2;
size++;
modCount++;
}
private static class Node
{
Object item;
Node next;
Node prev;
Node(Node node1, Object obj, Node node2)
{
item = obj;
next = node2;
prev = node1;
}
}
再来比较一下两者remove(int i)的源码实现区别:
ArrayList:
public Object remove(int i) {
rangeCheck(i); // 判断数组有没有下标越界
modCount++;
Object obj = elementData(i); // 取出下标为i的元素
int j = size - i - 1;
if (j > 0) // 如果j>0说明第i个元素不是该数组的最后一个元素
System.arraycopy(((Object) (elementData)), i + 1,
((Object) (elementData)), i, j);// 实现数组的复制
elementData[--size] = null; //如果j不大于0,说明j是最后一个元素了,则把最后一个元素直接指向空,并且自减1
return obj;
}
Object elementData(int i) {
return elementData[i];// elementData是Object数组
}
private void rangeCheck(int i) {
if (i >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(i));
else
return;
}
另外解释一下System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
src:源数组; srcPos:源数组要复制的起始位置; dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
举例说明:假如有一个ArrayList array,里面的元素为{2,5,7,4,9,6,10},size=7,如果要删除7,也就是删除index=2的数据;
src = array;dest = array;
System.arraycopy(src, 2+1,dest, 2, 4);
在src中,从index=2的下一位(也就是index=3)开始copy 4个数({4,9,6,10}),放到dest中,从index=2(也就是被删除的数据的位置)开始,结果为{2,5,4,9,6,10}
这样就完成了remove操作。
LinkedList:
LinkedList里的元素存放在Node里,Node里有三个field,分别是Object item、Node next、Node prev,它们分别是当前节点对象、当前节点的下一个对象、当前节点的前一个对象。
private static class Node
{
Object item;
Node next;
Node prev;
Node(Node node1, Object obj, Node node2)
{
item = obj;
next = node2;
prev = node1;
}
}
public Object remove(int i)
{
checkElementIndex(i);//判断有没有数组下标越界
return unlink(node(i));
}
Object unlink(Node node1)
{
Object obj = node1.item;//取出当前节点对象
Node node2 = node1.next;//取出当前节点对象的下一个对象
Node node3 = node1.prev;//取出当前节点对象的上一个对象
if(node3 == null) //如果node3==null为true,说明当前节点对象为first.
{
first = node2;
} else
{
node3.next = node2;
node1.prev = null;
}
if(node2 == null) //如果node2==null为true,说明当前节点对象为last.
{
last = node3;
} else
{
node2.prev = node3;
node1.next = null;
}
node1.item = null; //把当前节点对象指向空
size--;
modCount++;
return obj;
}