首頁 Java java教程 java中什麼情況下使用ArrayList和LinkedList?

java中什麼情況下使用ArrayList和LinkedList?

Nov 28, 2019 pm 04:10 PM
arraylist linkedlist

java中什麼情況下使用ArrayList和LinkedList?

什麼情況用ArrayList or LinkedList呢?

ArrayList 和LinkedList 是Java 集合框架中用來儲存對象引用列表的兩個類別。 ArrayList 和 LinkedList 都實作 List 介面。先對List做一個簡單的了解:

列表(list)是元素的有序集合,也稱為序列。它提供了基於元素位置的操作,有助於快速存取、新增和刪除清單中特定索引位置的元素。 List 介面實作了 Collection 和 Iterable 作為父介面。它允許儲存重複值和空值,支援透過索引存取元素。

讀完這篇文章要搞清楚的問題:ArrayList和LinkedList有什麼不同之處?什麼時候該用ArrayList什麼時候又該用LinkedList呢?

(推薦影片:java影片教學#)  

下面以增加和刪除元素為例比較ArrayList和LinkedList的不同之處

增加元素到列表尾端:

在ArrayList中增加元素到佇列尾端的程式碼如下:

public boolean add(E e){
   ensureCapacity(size+1);//确保内部数组有足够的空间
   elementData[size++]=e;//将元素加入到数组的末尾,完成添加
   return true;      
}
登入後複製

ArrayList中add()方法的效能決定於ensureCapacity()方法。 ensureCapacity()的實作如下:

public vod ensureCapacity(int minCapacity){
  modCount++;
  int oldCapacity=elementData.length;
  if(minCapacity>oldCapacity){    //如果数组容量不足,进行扩容
      Object[] oldData=elementData;
      int newCapacity=(oldCapacity*3)/2+1;  //扩容到原始容量的1.5倍
      if(newCapacitty<minCapacity)   //如果新容量小于最小需要的容量,则使用最小
                                                    //需要的容量大小
         newCapacity=minCapacity ;  //进行扩容的数组复制
         elementData=Arrays.copyof(elementData,newCapacity);
  }
}
登入後複製

可以看到,只要ArrayList的目前容量夠大,add()操作的效率非常高的。只有當ArrayList對容量的需求超出目前陣列大小時,才需要進行擴容。擴容的過程中,會進行大量的陣列複製操作。而陣列複製時,最終會呼叫System.arraycopy()方法,因此add()操作的效率還是相當高的。

LinkedList 的add()運算實作如下,它也將任意元素增加到佇列的尾端:

public boolean add(E e){
   addBefore(e,header);//将元素增加到header的前面
   return true;
}
登入後複製

其中addBefore()的方法實作如下:

private Entry<E> addBefore(E e,Entry<E> entry){
     Entry<E> newEntry = new Entry<E>(e,entry,entry.previous);
     newEntry.provious.next=newEntry;
     newEntry.next.previous=newEntry;
     size++;
     modCount++;
     return newEntry;
}
登入後複製

可見,LinkeList由於使用了鍊錶的結構,因此不需要維護容量的大小。從這一點上來說,它比ArrayList有一定的效能優勢,然而,每次的元素增加都需要新建一個Entry對象,並進行更多的賦值操作。在頻繁的系統呼叫中,對效能會產生一定的影響。

增加元素到列表任意位置

除了提供元素到List的尾端,List介面也提供了在任意位置插入元素的方法:void add(int index,E element);

由於實現的不同,ArrayList和LinkedList在這個方法上存在一定的性能差異,由於ArrayList是基於數組實現的,而數組是一塊連續的內存空間,如果在數組的任意位置插入元素,必然導致在該位置後的所有元素需要重新排列,因此,其效率相對會比較低。

以下程式碼是ArrayList中的實作:

public void add(int index,E element){
   if(index>size||index<0)
      throw new IndexOutOfBoundsException(
        "Index:"+index+",size: "+size);
         ensureCapacity(size+1);
         System.arraycopy(elementData,index,elementData,index+1,size-index);
         elementData[index] = element;
         size++;
}
登入後複製

 可以看到每次插入操作,都會進行一次陣列複製。而這個操作在增加元素到List尾端的時候是不存在的,大量的陣列重組操作會導致系統效能低。且插入元素在List中的位置越是靠前,陣列重組的開銷也越大。

而LinkedList此時顯示了優勢:

public void add(int index,E element){
   addBefore(element,(index==size?header:entry(index)));
}
登入後複製

可見,對LinkedList來說,在List的尾端插入資料與在任意位置插入資料是一樣的,不會因為插入的位置靠前而導致插入的方法性能降低。

刪除任意位置元素

對於元素的刪除,List介面提供了在任意位置刪除元素的方法:

public E remove(int index);
登入後複製

對ArrayList來說,remove()方法和add()方法是雷同的。在任意位置移除元素後,都要進行陣列的重組。 ArrayList的實作如下:

public E remove(int index){
   RangeCheck(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;
     return oldValue;
}
登入後複製

可以看到,在ArrayList的每一次有效的元素刪除操作後,都要進行陣列的重組。且刪除的位置越前,陣列重組時的開銷越大。

public E remove(int index){
  return remove(entry(index));         
}
private Entry<E> entry(int index){
  if(index<0 || index>=size)
      throw new IndexOutBoundsException("Index:"+index+",size:"+size);
      Entry<E> e= header;
      if(index<(size>>1)){//要删除的元素位于前半段
         for(int i=0;i<=index;i++)
             e=e.next;
     }else{
         for(int i=size;i>index;i--)
             e=e.previous;
     }
         return e;
}
登入後複製

在LinkedList的實作中,首先要透過循環找到要刪除的元素。若要刪除的位置處於List的前半段,則從前往後找;若其位置處於後半段,則從後往前找。因此無論要刪除較為靠前或靠後的元素都是非常有效率的;但要移除List中間的元素卻幾乎要遍歷完半個List,在List擁有大量元素的情況下,效率很低。

容量參數

容量參數是ArrayList和Vector等基於陣列的List的獨特效能參數。它表示初始化的陣列大小。當ArrayList所儲存的元素數量超過其已有大小時。它會進行擴容,數組的擴容會導致整個數組進行一次記憶體複製。因此合理的數組大小有助於減少數組擴容的次數,從而提高系統效能。

public  ArrayList(){
  this(10);  
}
public ArrayList (int initialCapacity){
   super();
   if(initialCapacity<0)
       throw new IllegalArgumentException("Illegal Capacity:"+initialCapacity)
      this.elementData=new Object[initialCapacity];
}
登入後複製

ArrayList提供了一個可以製定初始陣列大小的建構子:

public ArrayList(int initialCapacity)
登入後複製

现以构造一个拥有100万元素的List为例,当使用默认初始化大小时,其消耗的相对时间为125ms左右,当直接制定数组大小为100万时,构造相同的ArrayList仅相对耗时16ms。

遍历列表

遍历列表操作是最常用的列表操作之一,在JDK1.5之后,至少有3中常用的列表遍历方式:

● forEach操作

● 迭代器

● for循环。

String tmp;
long start=System.currentTimeMills();    //ForEach 
for(String s:list){
    tmp=s;
}
System.out.println("foreach spend:"+(System.currentTimeMills()-start));
start = System.currentTimeMills();
for(Iterator<String> it=list.iterator();it.hasNext();){    
   tmp=it.next();
}
System.out.println("Iterator spend;"+(System.currentTimeMills()-start));
start=System.currentTimeMills();
int size=;list.size();
for(int i=0;i<size;i++){                     
    tmp=list.get(i);
}
System.out.println("for spend;"+(System.currentTimeMills()-start));
登入後複製

构造一个拥有100万数据的ArrayList和等价的LinkedList,使用以上代码进行测试,测试结果:

java中什麼情況下使用ArrayList和LinkedList?

什么情况用ArrayList or LinkedList呢?

可以看到,最简便的ForEach循环并没有很好的性能表现,综合性能不如普通的迭代器,而是用for循环通过随机访问遍历列表时,ArrayList表项很好,但是LinkedList的表现却无法让人接受,甚至没有办法等待程序的结束。这是因为对LinkedList进行随机访问时,总会进行一次列表的遍历操作。性能非常差,应避免使用。

总结

ArrayList和LinkedList在性能上各有优缺点,都有各自所适用的地方,总的说来可以描述如下:

1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。

对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;

而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。

2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。

3.LinkedList不支持高效的随机元素访问。

4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

本文来自php中文网,java教程栏目,欢迎学习!  

以上是java中什麼情況下使用ArrayList和LinkedList?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java ArrayList遍歷時使用foreach和iterator刪除元素的差異是什麼? Java ArrayList遍歷時使用foreach和iterator刪除元素的差異是什麼? Apr 27, 2023 pm 03:40 PM

一、Iterator和foreach的區別多態差異(foreach底層就是Iterator)Iterator是一個介面類型,他不關心集合或數組的類型;for和foreach都需要先知道集合的類型,甚至是集合內元素的類型; 1.為啥說foreach底層就是Iterator寫的程式碼:反編譯程式碼:二、foreach與iterator時remove的差別先來看阿里java開發手冊但1的時候不會報錯,2的時候就會報錯(java. util.ConcurrentModificationException)首

如何在Java中檢查ArrayList是否包含某個元素? 如何在Java中檢查ArrayList是否包含某個元素? Sep 03, 2023 pm 04:09 PM

您可以利用List介面的contains()方法來檢查清單中是否存在物件。 contains()方法booleancontains(Objecto)如果此清單包含指定的元素,則傳回true。更正式地說,如果且僅當此列表包含至少一個元素e,使得(o==null?e==null:o.equals(e)),則傳回true。參數c-要測試其在此列表中是否存在的元素。傳回值如果此清單包含指定的元素,則傳回true。拋出ClassCastException-如果指定元素的類型與此清單不相容(可選)。 NullP

使用java的ArrayList.remove()函數移除ArrayList中的元素 使用java的ArrayList.remove()函數移除ArrayList中的元素 Jul 24, 2023 pm 01:21 PM

使用java的ArrayList.remove()函數移除ArrayList中的元素在Java中,ArrayList是一種常用的集合類,用於儲存和操作一組元素。 ArrayList類別提供了許多方法來增刪改查集合中的元素。其中一個使用頻率較高的方法是remove(),它可以移除ArrayList中的元素。 ArrayList的remove()方法有兩種重載形式,一

使用LinkedList類別的removeLast()方法刪除鍊錶中的最後一個元素 使用LinkedList類別的removeLast()方法刪除鍊錶中的最後一個元素 Jul 24, 2023 pm 05:13 PM

使用LinkedList類別的removeLast()方法刪除鍊錶中的最後一個元素LinkedList是Java集合框架中常見的一種資料結構,它以雙向鍊錶的形式儲存元素。透過LinkedList類別提供的方法,我們可以方便地對鍊錶進行操作,例如新增、刪除和修改元素。在某些場景下,我們可能需要刪除鍊錶中的最後一個元素。 LinkedList類別提供了removeLas

Java中ArrayList初始化容量大小為10的原因是什麼 Java中ArrayList初始化容量大小為10的原因是什麼 May 10, 2023 pm 02:19 PM

為什麼HashMap的初始化容量為16?在聊ArrayList的初始化容量時,要先來回顧HashMap的初始化容量。這裡以Java8源碼為例,HashMap中的相關因素有兩個:初始化容量及裝載因子:/***Thedefaultinitialcapacity-MUSTbeapoweroftwo.*/staticfinalintDEFAULT_INITIAL_CAPACITY=1>1);if(newCapacity-minCapacity0)newCapacityhuge

使用java的ArrayList.clear()函數清空ArrayList中的元素 使用java的ArrayList.clear()函數清空ArrayList中的元素 Jul 24, 2023 pm 02:04 PM

使用Java的ArrayList.clear()函數清空ArrayList中的元素在Java程式設計中,ArrayList是一種非常常用的資料結構,它可以動態地儲存和存取元素。然而,在某些情況下,我們可能需要清空ArrayList中的所有元素,以便重新使用或釋放記憶體。這時,就可以使用ArrayList的clear()函數來實作。 ArrayList.clear()

Java使用ArrayList類別的contains()函數來判斷元素是否存在 Java使用ArrayList類別的contains()函數來判斷元素是否存在 Jul 24, 2023 pm 07:33 PM

Java使用ArrayList類別的contains()函數來判斷元素是否存在在Java程式設計中,ArrayList是一個非常常用的資料結構。它提供了一種靈活的方法來儲存和操作一組資料。除了簡單的新增、刪除和存取元素之外,ArrayList還提供了一些有用的方法,例如contains()函數,用於判斷元素是否存在於ArrayList中。 contains()函數是A

Java程式為LinkedList新增元素 Java程式為LinkedList新增元素 Aug 26, 2023 pm 10:21 PM

LinkedList是JavaCollectionFramework的通用類別,它實作了List、Deque和Queue三個介面。它提供了LinkedList資料結構的功能,LinkedList是一種線性資料結構,其中每個元素相互連結。我們可以對LinkedList執行多種操作,包括新增、刪除和遍歷元素。要將元素加入LinkedList集合中,我們可以使用各種內建方法,例如add()、addFirst()和addLast()。我們將探索如何使用這些方法將元素新增至LinkedList。在Java

See all articles