淺談ArrayList和LinkedList到底誰(shuí)更快
一、ArrayList和LinkedList究竟誰(shuí)快
在Java中應(yīng)該都知道ArrayList和LinkedList,
一直以來(lái)的概念呢是
ArrayList在get(index)這個(gè)應(yīng)該比LinkedList快;
LinkedList比ArrayList在add(index,element)快;
兩者共同遍歷呢,應(yīng)該是一樣快的,畢竟都要循環(huán)遍歷一遍。
直到我寫(xiě)了一個(gè)測(cè)試類(lèi)
package com.lw;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
public class TestJDKList {
List<Integer> linkedList = new LinkedList<>();
List<Integer> arrayList = new ArrayList<>();
int length = 1000000;
@Test
public void testLinkedInsert(){
for (int i = 0; i < length; i++) {
linkedList.add(i);
}
long currentMi2 = System.currentTimeMillis();
linkedList.add(length/2,3);
long endTime2 = System.currentTimeMillis();
System.out.println("testLinkedInsert:" + (endTime2 - currentMi2)); // 9
}
@Test
public void testArrayInsert(){
for (int i = 0; i < length; i++) {
arrayList.add(i);
}
long currentMi2 = System.currentTimeMillis();
arrayList.add(length/2,3);
long endTime2 = System.currentTimeMillis();
System.out.println("testArrayInsert:" + (endTime2 - currentMi2)); // 1
}
@Test
public void testLinkedGet(){
for (int i = 0; i < length; i++) {
linkedList.add(i);
}
long currentMi2 = System.currentTimeMillis();
linkedList.get(length/2);
long endTime2 = System.currentTimeMillis();
System.out.println("testLinkedGet:" + (endTime2 - currentMi2)); // 5
}
@Test
public void testArrayGet(){
for (int i = 0; i < length; i++) {
arrayList.add(i);
}
long currentMi2 = System.currentTimeMillis();
arrayList.get(length/2);
long endTime2 = System.currentTimeMillis();
System.out.println("testArrayGet:" + (endTime2 - currentMi2)); // 0
}
@Test
public void testLinkedIter(){
for (int i = 0; i < length; i++) {
linkedList.add(i);
}
long currentMi2 = System.currentTimeMillis();
for (Integer i : linkedList) {
};
long endTime2 = System.currentTimeMillis();
System.out.println("testLinkedIter:" + (endTime2 - currentMi2)); // 26
}
@Test
public void testArrayIter(){
for (int i = 0; i < length; i++) {
arrayList.add(i);
}
long currentMi2 = System.currentTimeMillis();
for (Integer i : arrayList) {
};
long endTime2 = System.currentTimeMillis();
System.out.println("testArrayIter:" + (endTime2 - currentMi2)); // 11
}
@Test
public void testLinkedAdd() {
long currentMi2 = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
linkedList.add(i);
}
long endTime2 = System.currentTimeMillis();
System.out.println("testLinkedAdd:" + (endTime2 - currentMi2)); // 53
}
@Test
public void testArrayAdd(){
long currentMi1 = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
arrayList.add(i);
}
long endTime1 = System.currentTimeMillis();
System.out.println("testArrayAdd:" + (endTime1 - currentMi1)); // 35
}
}
二、結(jié)果
運(yùn)行了兩遍結(jié)果如下:
testLinkedInsert:7
testArrayInsert:0
testLinkedAdd:218
testArrayAdd:23
testLinkedGet:4
testArrayGet:0
testLinkedIter:14
testArrayIter:11
----------------第二遍分割線---------------------------------
testLinkedInsert:12
testArrayInsert:0
testLinkedIter:13
testArrayIter:12
testLinkedGet:3
testArrayGet:0
testLinkedAdd:119
testArrayAdd:23
顛覆三觀,ArrayList竟然無(wú)論怎樣都比LinkedList快??
三、循環(huán)Add
ArrayList的add源碼,它是把數(shù)據(jù)放在一個(gè)數(shù)組中
transient Object[] elementData;
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
而LinkedList源碼,是把數(shù)據(jù)放在Node對(duì)象中,有個(gè)前后指針。
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++;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
難道是前后指針這里花時(shí)間了么?
四、指定位置Get
再看get方法,
ArrayList的get,因?yàn)槭沁B續(xù)的內(nèi)存,所以取數(shù)據(jù)很快。
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
再看LinkedList的get,是通過(guò)指針遍歷的,直到是這個(gè)index為止。
這里還有判斷size,如果是size的前一半,則通過(guò)first節(jié)點(diǎn)往后去找,如果在后一半則通過(guò)last節(jié)點(diǎn)往前找,這樣會(huì)更快,所以LinkedList的查找其實(shí)也不慢。
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
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;
}
}
五、指定位置Add
ArrayList的add(index,element)
這里是可以擴(kuò)容的,將index后半段拷貝到index+1,然后在index插入一個(gè)新的,但沒(méi)想到這么快。
其實(shí)也能想到System.arraycopy是native,所以快也能理解
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++;
}
然后是LinkedList的add(index,element)
無(wú)非是指針的指向變化而已,但沒(méi)想到比上面的System.arraycopy還要慢,果然不愧為native方法。
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++;
}
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++;
}
所以項(xiàng)目中大部分用ArrayList也就是可以理解。
不過(guò)ArrayList是連續(xù)的內(nèi)存空間,在內(nèi)存空間很緊張情況下,LinkedList內(nèi)存利用率更高。
到此這篇關(guān)于淺談ArrayList和LinkedList到底誰(shuí)更快的文章就介紹到這了,更多相關(guān)ArrayList和LinkedList內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中ArrayList和LinkedList的區(qū)別詳解
- 區(qū)分Java中的ArrayList和LinkedList
- java 集合之實(shí)現(xiàn)類(lèi)ArrayList和LinkedList的方法
- Java中ArrayList和LinkedList之間的區(qū)別_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- java中ArrayList與LinkedList對(duì)比詳情
- java 中ArrayList與LinkedList性能比較
- Java中ArrayList和LinkedList的遍歷與性能分析
- 分析Java中ArrayList與LinkedList列表結(jié)構(gòu)的源碼
- 淺談 java中ArrayList、Vector、LinkedList的區(qū)別聯(lián)系
- JAVA LinkedList和ArrayList的使用及性能分析
相關(guān)文章
SpringBoot集成WebSocket【基于純H5】進(jìn)行點(diǎn)對(duì)點(diǎn)[一對(duì)一]和廣播[一對(duì)多]實(shí)時(shí)推送
Mybatis-Plus中分頁(yè)插件PaginationInterceptor的使用
SpringCloud LoadBalancer自定義負(fù)載均衡器使用解析
java模擬ajax訪問(wèn)另一個(gè)項(xiàng)目的controller代碼實(shí)例
Maven?pom.xml文件獲取當(dāng)前時(shí)間戳方式
詳解Spring中singleton?bean如何同時(shí)服務(wù)多個(gè)請(qǐng)求

