ArrayList 与 LinkedList性能比较
2017-05-04 11:14
351 查看
今天看到有人提问 arrayList 与 LinkedList 性能比较的问题,为此专门测试了下两者的插入,删除,访问效率
经过测试大概得出以下结论:
ArrayList 与 LinkedList 在顺序插入时(末尾插入),数据量较小时(100000以内)LinkedList的插入效率优于 arrayList(但不明显,最多几倍的差距),但数据量更大时(40w 以上)此时顺序插入 arraylist 的插入性能明显优于 linkedlist.但如果一直在 list 的位置0插入,linkedList 的插入性能对 arrayList 有指数级性能优势.
可以查看两者的插入代码分析以上现象:
先看 arrayList 的插入代码,主要代码如下:
分析以上代码可以看到,arrayList 在顺序插入时,如果数据容量不够,会经常扩容,其中扩容代码
对于 linkedList,插入的主要代码逻辑如下:
可见对于末尾插入,linkedlist 每次打操作都是直接在链表末尾插入数据,对于位置0的插入,linkedlist 的操作与在末尾插入基本一致,(linkedlist 对于制定位置操作会首先检查靠近末尾还是靠近头元素,会从靠近的一端进行遍历),因此 linkedList 对于中间部分的插入操作的耗时会基本花在查找元素上
对于插入操作,两者可以得出以下结论:
1.对于少量元素,尽量使用 arrayList
2.对于大量元素(10w 以上),没有频繁的随机读取操作,且有大量的 list 前部的插入操作(前10%),此时可以选用 Linkedlist
3.尽量使用 arrayList,除非使用 LinkedList 时的速度是 arrayList 的10倍以上
对于删除操作:
对于大量数据,如果一直从 list 开始位置开始删除,linkedlist 对 arrayList 有指数级优势,但如果从末尾位置开始删除,arrayList 对 linkedList有较大优势
arraylist删除代码如下
主要耗时代码为:
对于 linkedList 的删除代码:
对于 linkedList 来说删除的主要耗时还是花在查找元素上
因此对于删除操作这两者的建议如下:
对于少量数据的删除建议使用 arrayList
对于大量数据,总是删除靠前数据时,建议使用 linkedList
其余情况使用 arrayList
综合以上插入与删除,对于这两种 list 的综合建议:
99%的情况用ArrayList,还有1%的情况是:
1、超大List,超大指至少十几万个元素,并且还需要频繁添加删除(在 list 开始部分),但不需要频繁访问
2、当你发现ArrayList比LinkedList耗时多一个数量级的时候
经过测试大概得出以下结论:
ArrayList 与 LinkedList 在顺序插入时(末尾插入),数据量较小时(100000以内)LinkedList的插入效率优于 arrayList(但不明显,最多几倍的差距),但数据量更大时(40w 以上)此时顺序插入 arraylist 的插入性能明显优于 linkedlist.但如果一直在 list 的位置0插入,linkedList 的插入性能对 arrayList 有指数级性能优势.
可以查看两者的插入代码分析以上现象:
先看 arrayList 的插入代码,主要代码如下:
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } 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); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; 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); } public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
分析以上代码可以看到,arrayList 在顺序插入时,如果数据容量不够,会经常扩容,其中扩容代码
Arrays.copyOf(elementData, newCapacity);会消耗大量时间,但如果数据量较大,此时扩容次数明显下降(扩容总是会在当前容量的2倍),因此扩容消耗的时间平均下来明显降低,但对于每次都插入指定位置0的时候
System.arraycopy(elementData, index, elementData, index + 1,size - index);每次都会执行这个代码,数组的拷贝会浪费大量时间,因此插入时间会呈指数级增长
对于 linkedList,插入的主要代码逻辑如下:
public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = new Node<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; } Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
可见对于末尾插入,linkedlist 每次打操作都是直接在链表末尾插入数据,对于位置0的插入,linkedlist 的操作与在末尾插入基本一致,(linkedlist 对于制定位置操作会首先检查靠近末尾还是靠近头元素,会从靠近的一端进行遍历),因此 linkedList 对于中间部分的插入操作的耗时会基本花在查找元素上
对于插入操作,两者可以得出以下结论:
1.对于少量元素,尽量使用 arrayList
2.对于大量元素(10w 以上),没有频繁的随机读取操作,且有大量的 list 前部的插入操作(前10%),此时可以选用 Linkedlist
3.尽量使用 arrayList,除非使用 LinkedList 时的速度是 arrayList 的10倍以上
对于删除操作:
对于大量数据,如果一直从 list 开始位置开始删除,linkedlist 对 arrayList 有指数级优势,但如果从末尾位置开始删除,arrayList 对 linkedList有较大优势
arraylist删除代码如下
public E remove(int index) { rangeCheck(index); modCount++; E oldValue = 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; }
主要耗时代码为:
System.arraycopy(elementData, index+1, elementData, index, numMoved);,每一次删除 arrayList 都需要将被删除元素之后的所有元素复制一遍
对于 linkedList 的删除代码:
public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { first = next; } else { prev.next = next; x.prev = null; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; } Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
对于 linkedList 来说删除的主要耗时还是花在查找元素上
因此对于删除操作这两者的建议如下:
对于少量数据的删除建议使用 arrayList
对于大量数据,总是删除靠前数据时,建议使用 linkedList
其余情况使用 arrayList
综合以上插入与删除,对于这两种 list 的综合建议:
99%的情况用ArrayList,还有1%的情况是:
1、超大List,超大指至少十几万个元素,并且还需要频繁添加删除(在 list 开始部分),但不需要频繁访问
2、当你发现ArrayList比LinkedList耗时多一个数量级的时候
相关文章推荐
- Java Collections Framework - Java集合框架之List篇 ArrayList与LinkedList等的性能比较
- ArrayList及LinkedList遍历方式及性能比较
- LinkedList与ArrayList的性能比较
- ArrayList和LinkedList性能比较分析
- ArrayList和LinkedList区别,性能比较
- Java性能优化-Arraylist与Linkedlist整改查性能比较的简介与内容
- ArrayList和LinkedList性能比较
- ArrayList和LinkedList的各项操作性能比较
- ArrayList和LinkedList性能比较
- ArrayList、LinkedList、Vector性能比较
- 既然LinkedList比ArrayList性能和易用行好那么多 为啥我们还是用ArrayList用的比较多呢?
- ArrayList和LinkedList的各项操作性能比较
- Java Collections Framework - Java集合框架之List篇 ArrayList与LinkedList等的性能比较
- 关于LinkedList和ArrayList 插入元素的性能比较疑惑,知道的请指教......
- JAVA集合类之ArrayList和LinkedList性能比较
- ArrayList与LinkedList性能比较
- Java中arraylist和linkedlist源码分析与性能比较
- 比较List和ArrayList的性能及ArrayList和LinkedList优缺点
- 比较Java数组,ArrayList,LinkedList,Vector 性能比较