提高你的Java代码质量吧:频繁插入和删除时使用LinkedList(二)

2014-11-24 09:44:08 · 作者: · 浏览: 1
}
public E remove(int index){
//下标校验
RangeCheck(index);
//修改计数器+1
modCount++;
//记录要删除的元素
E oldValue = (E)elementData(index);
//有多少个元素向前移动
int numMoved = size - index - 1;
if(numMoved > 0)
//index后的元素向前移动一位
System.arraycopy(elementData,index + 1,elementData,index,numMoved);
//列表长度减1,并且最后一位设为null
elementData[--size] = null;
//返回删除的值
return oldValue;
}
注意看,index位置后的元素都向前移动了一位,最后一个位置空出来了,这又是一次数组拷贝,和插入一样,如果数据量大,删除动作必然会暴露出性能和效率方面的问题。
我们再来看看LinkedList的删除动作,比如删除指定位置元素,删除头元素等。我们看看最基本的删除指定位置元素的方法remove,源代码如下:
[java] private E remove(Entry e){
//取得原始值
E result = e.element;
//前节点next指向当前节点的next
e.previous.next = e.next;
//后节点的previouse指向当前节点的previous
e.next.previous = e.previous;
//置空当前节点的next和previous
e.next = e.previous= null;
//当前元素置空
e.element = null;
//列表长度减1
size --;
//修改计数器+1
modCount++;
return result;
}
private E remove(Entry e){
//取得原始值
E result = e.element;
//前节点next指向当前节点的next
e.previous.next = e.next;
//后节点的previouse指向当前节点的previous
e.next.previous = e.previous;
//置空当前节点的next和previous
e.next = e.previous= null;
//当前元素置空
e.element = null;
//列表长度减1
size --;
//修改计数器+1
modCount++;
return result;
}
这也是双向链表的标准删除算法,没有任何耗时的操作,全部是引用指针的改变,效率自然就更高了。
实际测试可知,处理大批量的删除操作,LinkedList比ArrayList块40倍以上。
3.修改元素
写操作还有一个动作:修改元素,在这点上LinkedList输给了ArrayList,这是因为,LinkedList是顺序存取的,因此定位元素必然是一个遍历的过程,效率大大折扣。
我们来开set方法的代码:
[java] public E set(int index,E element){
//定位节点
Entry e = entry(index);
E oldVal = e.element;
//节点元素替换
e.element = element;
return oldVal;
}
public E set(int index,E element){
//定位节点
Entry e = entry(index);
E oldVal = e.element;
//节点元素替换
e.element = element;
return oldVal;
}
看似很简洁,这里使用了entry方法定位元素。而LinkedList这种顺序取列表的元素定位方式会折半遍历,这是一个极其耗时的操作。而ArrayList的修改动作则是数组元素的直接替换,简单高效。
在修改动作上,LinkedList比ArrayList慢的多,特别是进行大量修改的时候,完全不是在一个数量级上。
三、建议
经过上面的源码分析完成了LinkedList与ArrayList之间的PK,其中LinkedList胜两局:删除和插入效率高;ArrayList胜一局:修改元素效率高。
如果有大量的写操作(更多的插入和删除动作),推荐使用LinkedList。不过何为少量,何为大量呢?
这就依赖于正在开发的 系统了,如果是一个实时的交易系统,即使写操作少,,使用LinkedList也比ArrayList合适,因为此类系统争分夺秒,多N个毫秒就可能会造成交易数据不准确。如果对于一个批量系统来说,几十毫秒、几百毫秒,甚至是几千毫秒的差别意义并不大,这时使用LinkedList还是ArrayList就看个人爱好了。当然,如果系统处于性能临界点,那就必须使用LinkedList。