List在平時的開發當中用的也很多,但是一般都是面向接口編程,所以使用的是List類型,但是都是用ArrayList或者LinkedList進行相關操作。本文章主要講解JDK源碼之ArrayList和LinkedList。
ArrayList底層采用的是數組的形式維護的,主要的方法有add,remove,size,contains,toArray等相關方法。add其實很簡單,底層就是增加數組的長度,然后將要加入的元素放進數組。其實現方式方法為:this.elementData[(this.size++)] = paramE,在此操作之前,會增加將數組的長度加1,以放入新加的元素進入到當前數組中,也就實現了List的增加功能。但是,如果要想插入到指定的位置,操作就復雜一些。它會將當前數組向后移動1位,使用的是System.arraycopy復制后面的元素,然后將指定的元素插入。這樣的時間就是代價。所以在插入元素比較多的情況下,優先使用Linkedlist,待會會做介紹。remove道理是一樣的。不過remove有重載。當為下標int時,它會將指定的元素復制,然后將指定下標的元素設置為null,這樣就實現了指定下標刪除的功能。但是重載的不一樣。他接收Object類型,這樣,不管list中存儲的是什么類型,都可以進行remove。使用這個方法時,它會搜索符合條件的元素,并取到下標,然后使用firstRemove方法移除指定的元素。當然這種方法只能移除第一個元素,如果想要移除匹配的所有元素,就得遍歷,或者使用removeAll方法了。需要注意的是,removeAll接收參數為Collection的。至于ArrayList中的size就很簡單了,因為底層是數組,所以只需要返回當前數組的大小就是此list長度了。contains返回的是當前數組的下標,使用方法indexOf,如果沒有則indexOf回返-1。toArray方法返回的是list數組的形式,直接使用Array中的copy即可。其實ArrayList中有個重要的方法,就是迭代器,不過迭代器是在父類AbstractList中的,且放在了內部類Itr中,使用時,直接定義一個迭代器Iterator,然后調用iterator方法,此方法返回內部類的對象,此時就可以通過這個對象進行迭代,包括方法next和hasNext。這個是最常用的,此處重點分析實現。我們可以先定義一個接口類型的Iterator,使用iterator()直接獲取對象,此方法返回的是一個Itr對象(內部類,存在于父類中),這個內部類包含了next和hasNext,然后就可以使用這個對象去遍歷數組。hasNext即判斷當前是否還有元素,這個方法使用了游標的概念,當前游標與當前數組的大小是否相等,返回true或false。然后使用hasNext拿出值,并將游標向后移動一位。這樣就可以遍歷數組了。當然這個方法是在父類中,在ArrayList中時看不見的。迭代器使用了典型的面向接口編程思想,只是定義了接口類型,然后去調用實現類中相關的方法。(面向接口編程后期會做具體分析)。API中說使用了迭代器以后,就不能對該list進行更改了,具體原因我在JDK中沒有找出。初步分析是由于游標的緣故,希望知道的網友給出答案。(ArrayList不是線程安全的,API中講到,如果他線程安全,只需將其放到Collections.synchronizedList中,這個在工作中還真的很少用到,看了JDK的源碼,其做法是將list放進SynchronizedList代碼塊中,具體的實現不看了,反正我很少用到。
LinkedList跟ArrayList很多方法的功能都是一樣的,但是實現方式方法卻很不一樣。他的底層使用的是鏈表實現的,使用了內部類Entry,Entry包含了element、next、PRevious。當實例化list的時候,就會對這三個變量進行賦值,后期的一切操作都是圍繞著這三個變量展開。在這同樣先分析方法add,remove,size,contains方法。在介紹add之前先介紹addBefore。addBefore是將當前元素封裝成一個Entry,然后next和previous分別重新賦值,這樣就實現了鏈表的向后移動,即望鏈表上加入元素。鏈表這個東西有興趣的可以自己看看數據結構。add方法調用的就是addBefore,但是對于鏈表中的next使用的是header,這樣就將元素加入到了鏈表。此list的add方法代價是巨大的,因為他要移動鏈表的next和previous,沒有ArrayList中簡單,直接賦值就可以了。remove方法的實現原理差不多,也是對鏈表進行的操作。size方法就是返回當前鏈表的長度,不做過多介紹。contains方法就是對鏈表進行的遍歷,一步一步移動鏈表,并進行匹配。toArray方法底層的實現是將鏈表的元素取出來,放進一個數組,并返回該數組,而病史想ArrayList中那樣,直接返回數組。LinkedList的迭代器與ArrayList的迭代器相似,但是底層的實現不一樣,如hasNext,他是用的是this.nextIndex來判斷是否有下一個元素,而并不是查看數組中是否有元素。關于LinkedList需要深入的看下,今天我只看了一些表面的知識,以后會補充上來。
今晚就分析到這,其實這兩個類中還有很多地方需要看,希望廣大網友提供很好的分析,相互學習。
|
新聞熱點
疑難解答