欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中ArrayList 、LinkList的區(qū)別分析

 更新時(shí)間:2013年05月07日 10:00:35   作者:  
java中ArrayList 、LinkList的區(qū)別分析,需要的朋友可以參考一下

1.ArrayList是實(shí)現(xiàn)了基于動(dòng)態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。
     2.對(duì)于隨機(jī)訪問get和set,ArrayList優(yōu)于LinkedList,因?yàn)锳rrayList可以隨機(jī)定位,而LinkedList要移動(dòng)指針一步一步的移動(dòng)到節(jié)點(diǎn)處。(參考數(shù)組與鏈表來思考)
     3.對(duì)于新增和刪除操作add和remove,LinedList比較占優(yōu)勢,只需要對(duì)指針進(jìn)行修改即可,而ArrayList要移動(dòng)數(shù)據(jù)來填補(bǔ)被刪除的對(duì)象的空間。

ArrayList和LinkedList是兩個(gè)集合類,用于存儲(chǔ)一系列的對(duì)象引用(references)。例如我們可以用ArrayList來存儲(chǔ)一系列的String或者Integer。那么ArrayList和LinkedList在性能上有什么差別呢?什么時(shí)候應(yīng)該用ArrayList什么時(shí)候又該用LinkedList呢?

一.時(shí)間復(fù)雜度

首先一點(diǎn)關(guān)鍵的是,ArrayList的內(nèi)部實(shí)現(xiàn)是基于基礎(chǔ)的對(duì)象數(shù)組的,因此,它使用get方法訪問列表中的任意一個(gè)元素時(shí)(random-access),它的速度要比LinkedList快。LinkedList中的get方法是按照順序從列表的一端開始檢查,直到另外一端。對(duì)LinkedList而言,訪問列表中的某個(gè)指定元素沒有更快的方法了。

假設(shè)我們有一個(gè)很大的列表,它里面的元素已經(jīng)排好序了,這個(gè)列表可能是ArrayList類型的也可能是LinkedList類型的,現(xiàn)在我們對(duì)這個(gè)列表來進(jìn)行二分查找(binary search),比較列表是ArrayList和LinkedList時(shí)的查詢速度,看下面的程序:

復(fù)制代碼 代碼如下:

package com.mangocity.test;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class TestList ...{
     public static final int N=50000;
     public static List values;
     static...{
         Integer vals[]=new Integer[N];
         Random r=new Random();
         for(int i=0,currval=0;i<N;i++)...{
             vals=new Integer(currval);
             currval+=r.nextInt(100)+1;
         }
         values=Arrays.asList(vals);
     }
     static long timeList(List lst)...{
         long start=System.currentTimeMillis();
         for(int i=0;i<N;i++)...{
             int index=Collections.binarySearch(lst, values.get(i));
             if(index!=i)
                 System.out.println("***錯(cuò)誤***");
         }
         return System.currentTimeMillis()-start;
     }
     public static void main(String args[])...{
         System.out.println("ArrayList消耗時(shí)間:"+timeList(new ArrayList(values)));
         System.out.println("LinkedList消耗時(shí)間:"+timeList(new LinkedList(values)));
     }
}

 我得到的輸出是:ArrayList消耗時(shí)間:15

                 LinkedList消耗時(shí)間:2596

這個(gè)結(jié)果不是固定的,但是基本上ArrayList的時(shí)間要明顯小于LinkedList的時(shí)間。因此在這種情況下不宜用LinkedList。二分查找法使用的隨機(jī)訪問(randomaccess)策略,而LinkedList是不支持快速的隨機(jī)訪問的。對(duì)一個(gè)LinkedList做隨機(jī)訪問所消耗的時(shí)間與這個(gè)list的大小是成比例的。而相應(yīng)的,在ArrayList中進(jìn)行隨機(jī)訪問所消耗的時(shí)間是固定的。

這是否表明ArrayList總是比LinkedList性能要好呢?這并不一定,在某些情況下LinkedList的表現(xiàn)要優(yōu)于ArrayList,有些算法在LinkedList中實(shí)現(xiàn)時(shí)效率更高。比方說,利用Collections.reverse方法對(duì)列表進(jìn)行反轉(zhuǎn)時(shí),其性能就要好些。

看這樣一個(gè)例子,假如我們有一個(gè)列表,要對(duì)其進(jìn)行大量的插入和刪除操作,在這種情況下LinkedList就是一個(gè)較好的選擇。請(qǐng)看如下一個(gè)極端的例子,我們重復(fù)的在一個(gè)列表的開端插入一個(gè)元素:

復(fù)制代碼 代碼如下:

package com.mangocity.test;
import java.util.*;
public class ListDemo {
     static final int N=50000;
     static long timeList(List list){
     long start=System.currentTimeMillis();
     Object o = new Object();
     for(int i=0;i<N;i++)
         list.add(0, o);
     return System.currentTimeMillis()-start;
     }
     public static void main(String[] args) {
         System.out.println("ArrayList耗時(shí):"+timeList(new ArrayList()));
         System.out.println("LinkedList耗時(shí):"+timeList(new LinkedList()));
     }
}

  這時(shí)我的輸出結(jié)果是:ArrayList耗時(shí):2463

                           LinkedList耗時(shí):15

這和前面一個(gè)例子的結(jié)果截然相反,當(dāng)一個(gè)元素被加到ArrayList的最開端時(shí),所有已經(jīng)存在的元素都會(huì)后移,這就意味著數(shù)據(jù)移動(dòng)和復(fù)制上的開銷。相反的,將一個(gè)元素加到LinkedList的最開端只是簡單的為這個(gè)元素分配一個(gè)記錄,然后調(diào)整兩個(gè)連接。在LinkedList的開端增加一個(gè)元素的開銷是固定的,而在ArrayList的開端增加一個(gè)元素的開銷是與ArrayList的大小成比例的。

二.空間復(fù)雜度

在LinkedList中有一個(gè)私有的內(nèi)部類,定義如下:

private static class Entry {
         Object element;
         Entry next;
         Entry previous;
     }

每個(gè)Entry對(duì)象reference列表中的一個(gè)元素,同時(shí)還有在LinkedList中它的上一個(gè)元素和下一個(gè)元素。一個(gè)有1000個(gè)元素的LinkedList對(duì)象將有1000個(gè)鏈接在一起的Entry對(duì)象,每個(gè)對(duì)象都對(duì)應(yīng)于列表中的一個(gè)元素。這樣的話,在一個(gè)LinkedList結(jié)構(gòu)中將有一個(gè)很大的空間開銷,因?yàn)樗鎯?chǔ)這1000個(gè)Entity對(duì)象的相關(guān)信息。

ArrayList使用一個(gè)內(nèi)置的數(shù)組來存儲(chǔ)元素,這個(gè)數(shù)組的起始容量是10.當(dāng)數(shù)組需要增長時(shí),新的容量按如下公式獲得:新容量=(舊容量*3)/2+1,也就是說每一次容量大概會(huì)增長50%。這就意味著,如果你有一個(gè)包含大量元素的ArrayList對(duì)象,那么最終將有很大的空間會(huì)被浪費(fèi)掉,這個(gè)浪費(fèi)是由ArrayList的工作方式本身造成的。如果沒有足夠的空間來存放新的元素,數(shù)組將不得不被重新進(jìn)行分配以便能夠增加新的元素。對(duì)數(shù)組進(jìn)行重新分配,將會(huì)導(dǎo)致性能急劇下降。如果我們知道一個(gè)ArrayList將會(huì)有多少個(gè)元素,我們可以通過構(gòu)造方法來指定容量。我們還可以通過trimToSize方法在ArrayList分配完畢之后去掉浪費(fèi)掉的空間。

三.總結(jié)

ArrayList和LinkedList在性能上各有優(yōu)缺點(diǎn),都有各自所適用的地方,總的說來可以描述如下:

性能總結(jié):

- add()操作 delete()操作 insert操作 index取值操作 iterator取值操作
ArrayList/Vector/Stack 極優(yōu) 極優(yōu)
LinkedList 極優(yōu)

1.對(duì)ArrayList和LinkedList而言,在列表末尾增加一個(gè)元素所花的開銷都是固定的。對(duì)ArrayList而言,主要是在內(nèi)部數(shù)組中增加一項(xiàng),指向所添加的元素,偶爾可能會(huì)導(dǎo)致對(duì)數(shù)組重新進(jìn)行分配;而對(duì)LinkedList而言,這個(gè)開銷是統(tǒng)一的,分配一個(gè)內(nèi)部Entry對(duì)象。

2.在ArrayList的中間插入或刪除一個(gè)元素意味著這個(gè)列表中剩余的元素都會(huì)被移動(dòng);而在LinkedList的中間插入或刪除一個(gè)元素的開銷是固定的。

3.LinkedList不支持高效的隨機(jī)元素訪問。

4.ArrayList的空間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗相當(dāng)?shù)目臻g

可以這樣說:當(dāng)操作是在一列數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能;當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù),并且按照順序訪問其中的元素時(shí),就應(yīng)該使用LinkedList了。

java中ArrayList 、List區(qū)別

List集合
    List繼承自Collection接口。List是一種有序集合,List中的元素可以根據(jù)索引(順序號(hào):元素在集合中處于的位置信息)進(jìn)行取得/刪除/插入操作。

    跟Set集合不同的是,List允許有重復(fù)元素。對(duì)于滿足e1.equals(e2)條件的e1與e2對(duì)象元素,可以同時(shí)存在于List集合中。當(dāng)然,也有List的實(shí)現(xiàn)類不允許重復(fù)元素的存在。
   同時(shí),List還提供一個(gè)listIterator()方法,返回一個(gè)ListIterator接口對(duì)象,和Iterator接口相比,ListIterator添加元素的添加,刪除,和設(shè)定等方法,還能向前或向后遍歷。

List跟Collection的關(guān)系:
java.util.Collection [I]
+--java.util.List [I]
   +--java.util.ArrayList [C]
   +--java.util.LinkedList [C]
   +--java.util.Vector [C]
      +--java.util.Stack [C]

List接口的實(shí)現(xiàn)類主要有ArrayList,LinkedList,Vector,Stack等。

父子關(guān)系.
   List是一個(gè)接口,ArrayList繼承與這個(gè)接口并實(shí)現(xiàn)了它.
   用的時(shí)候一般都用ArrayList.沒用過List. 可以這么用:List list = new ArrayList();

Collection接口
    Collection是最基本的集合接口,一個(gè)Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,JavaSDK提供的類都是繼承自Collection的“子接口”如List和Set。
    所有實(shí)現(xiàn)Collection接口的類都必須提供兩個(gè)標(biāo)準(zhǔn)的構(gòu)造函數(shù):無參數(shù)的構(gòu)造函數(shù)用于創(chuàng)建一個(gè)空的Collection,有一個(gè)Collection參數(shù)的構(gòu)造函數(shù)用于創(chuàng)建一個(gè)新的Collection,這個(gè)新的Collection與傳入的Collection有相同的元素。后一個(gè)構(gòu)造函數(shù)允許用戶復(fù)制一個(gè)Collection。

     如何遍歷Collection中的每一個(gè)元素?不論Collection的實(shí)際類型如何,它都支持一個(gè)iterator()的方法,該方法返回一個(gè)迭代子,使用該迭代子即可逐一訪問Collection中每一個(gè)元素。典型的用法如下:
    Iterator it = collection.iterator(); // 獲得一個(gè)迭代子
    while(it.hasNext()) {
                             Object obj = it.next(); // 得到下一個(gè)元素
       }
由Collection接口派生的兩個(gè)接口是List和Set。

    List接口:
    List是有序的Collection,使用此接口能夠精確的控制每個(gè)元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似于數(shù)組下標(biāo))來訪問List中的元素,這類似于Java的數(shù)組。
和下面要提到的Set不同,List允許有相同的元素。
除了具有Collection接口必備的iterator()方法外,List還提供一個(gè)listIterator()方法,返回一個(gè)ListIterator接口,和標(biāo)準(zhǔn)的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設(shè)定元素,還能向前或向后遍歷。
    實(shí)現(xiàn)List接口的常用類有LinkedList,ArrayList,Vector和Stack。

     LinkedList類
     LinkedList實(shí)現(xiàn)了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊(duì)列(queue)或雙向隊(duì)列(deque)。
    注意LinkedList沒有同步方法。如果多個(gè)線程同時(shí)訪問一個(gè)List,則必須自己實(shí)現(xiàn)訪問同步。一種解決方法是在創(chuàng)建List時(shí)構(gòu)造一個(gè)同步的List:
List list = Collections.synchronizedList(new LinkedList(...));

ArrayList類
ArrayList實(shí)現(xiàn)了可變大小的數(shù)組。它允許所有元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運(yùn)行時(shí)間為常數(shù)。但是add方法開銷為分?jǐn)偟某?shù),添加n個(gè)元素需要O(n)的時(shí)間。其他的方法運(yùn)行時(shí)間為線性。
每個(gè)ArrayList實(shí)例都有一個(gè)容量(Capacity),即用于存儲(chǔ)元素的數(shù)組的大小。這個(gè)容量可隨著不斷添加新元素而自動(dòng)增加,但是增長算法并沒有定義。當(dāng)需要插入大量元素時(shí),在插入前可以調(diào)用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。

總結(jié)
  如果涉及到堆棧,隊(duì)列等操作,應(yīng)該考慮用List,對(duì)于需要快速插入,刪除元素,應(yīng)該使用LinkedList,如果需要快速隨機(jī)訪問元素,應(yīng)該使用ArrayList。
      盡量返回接口而非實(shí)際的類型,如返回List而非ArrayList,這樣如果以后需要將ArrayList換成LinkedList時(shí),客戶端代碼不用改變。這就是針對(duì)抽象編程。

相關(guān)文章

  • 通過簡單方法實(shí)現(xiàn)spring boot web項(xiàng)目

    通過簡單方法實(shí)現(xiàn)spring boot web項(xiàng)目

    這篇文章主要介紹了通過簡單方法實(shí)現(xiàn)spring boot web項(xiàng)目,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Spring的Model?和?Map的原理源碼解析

    Spring的Model?和?Map的原理源碼解析

    這篇文章主要介紹了Spring的Model?和?Map的原理解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • mybatis分頁及模糊查詢功能實(shí)現(xiàn)

    mybatis分頁及模糊查詢功能實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)為大家詳細(xì)介紹了mybatis實(shí)現(xiàn)分頁及模糊查詢功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • idea的spring boot項(xiàng)目實(shí)現(xiàn)更改端口號(hào)操作

    idea的spring boot項(xiàng)目實(shí)現(xiàn)更改端口號(hào)操作

    這篇文章主要介紹了idea的spring boot項(xiàng)目實(shí)現(xiàn)更改端口號(hào)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java中@RestController注解使用

    Java中@RestController注解使用

    在Spring框架中,@RestController注解是一個(gè)非常重要的注解,它用于將一個(gè)類標(biāo)記為RESTful風(fēng)格的控制器,本文就來介紹一下Java中@RestController注解使用,感興趣的可以了解一下
    2023-11-11
  • 深入淺出MyBatis中映射文件和實(shí)體類的關(guān)聯(lián)性

    深入淺出MyBatis中映射文件和實(shí)體類的關(guān)聯(lián)性

    這篇文章主要介紹了MyBatis中映射文件和實(shí)體類的關(guān)聯(lián)性的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • Java?設(shè)計(jì)模式以虹貓藍(lán)兔的故事講解簡單工廠模式

    Java?設(shè)計(jì)模式以虹貓藍(lán)兔的故事講解簡單工廠模式

    簡單工廠模式是屬于創(chuàng)建型模式,又叫做靜態(tài)工廠方法(Static Factory Method)模式,但不屬于23種GOF設(shè)計(jì)模式之一。簡單工廠模式是由一個(gè)工廠對(duì)象決定創(chuàng)建出哪一種產(chǎn)品類的實(shí)例。簡單工廠模式是工廠模式家族中最簡單實(shí)用的模式,可以理解為是不同工廠模式的一個(gè)特殊實(shí)現(xiàn)
    2022-03-03
  • 在Spring中如何使用動(dòng)態(tài)代理?

    在Spring中如何使用動(dòng)態(tài)代理?

    上篇文章記錄自定義切面,下邊記錄使用注解來編寫自定義切面,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java利用StringTokenizer分割字符串的實(shí)現(xiàn)

    java利用StringTokenizer分割字符串的實(shí)現(xiàn)

    利用java.util.StringTokenizer的方法,可以將一個(gè)字符串拆分為一系列的標(biāo)記,本文就來介紹一下java利用StringTokenizer分割字符串的實(shí)現(xiàn),感興趣的可以了解一下
    2023-10-10
  • 如何用java計(jì)算兩個(gè)時(shí)間相差多少小時(shí)

    如何用java計(jì)算兩個(gè)時(shí)間相差多少小時(shí)

    最近工作中遇到需要計(jì)算時(shí)間差,下面這篇文章主要給大家介紹了關(guān)于如何用java計(jì)算兩個(gè)時(shí)間相差多少小時(shí)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12

最新評(píng)論