程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2SE >> J2SE - 集合框架(1)

J2SE - 集合框架(1)

編輯:J2SE

我們都知道,當想要保存一組基本類型數據時,數組是最有效的保存方式,也是推薦使用這種方式的。但是數組是固有大小的,當運行時才知道大小的程序,這種方式使用就受限制了,這就是Java容器類產生的原因。Java集合類有幾個特點:首先,這種容器是高性能的,對基本數據集合(動態數組、鏈接表、樹和散列表)的實現是高效率的。第二,容器類允許不同類型的類集合以相同的方式和高度互操作方式工作。第三,容器類是容易擴展或修改的。容器類的常用的基本類型有List、Set和Map,這些對象類型也稱為集合類,但是在Java中使用了Collection這個名字來指代該類庫的一個特殊子集,所以業界使用了范圍更廣泛的“容器”來稱呼。

Collection:是一個接口,它位於集合框架層次結構的頂層,繼承自Iterable接口,說明是可以用Iterator迭代器來訪問該集合中的元素的。又有List、Set和Queue接口繼承Collection接口,直接實現該接口的是一個叫AbstractCollection的抽象類,該抽象類以最大限度地減少了實現此接口所需的工作。

List:繼承自Collection接口,表示有序的、可包括重復元素的列表。同時擁有Collection內的方法外,還添加了大量的方法,使得可以在List的中間插入和刪除元素。實現該接口的基本類有ArrayList和LinkedList. ArrayList:擅長於對元素的隨機訪問,但是在插入和刪除元素時效率較慢。其實,看看ArrayList類實現的源代碼就知道,ArrayList是以線性表的數據結構形式存取數據的,初始化的表大小為10,下面就有幾個經常用到的核心方法:add(E e):在當前表的末尾插入元素,如果在前面表不滿的情況下,也是很高效的,直接插入到末尾,但是如果在當前表已經滿的情況下,就要重新生成一個比當前表大小更大的新表,新表的大小是當前表大小的1.5倍加1,比如當前表長度為20的,新表的大小就為31,還需要把當前表元素復制到新表中去,然後把當前表引用指向新表,最後把數值插入到表末尾,所以這種操作是非常低效的。

add(int index,E element):在指定索引位置插入元素,檢查表大小和重新追加表大小和上面的add(E e)方式是一樣的。最後是要把index以後的元素都是要依次往後移一個大小,然後把元素插入到index位置上去。涉及到表的復制和表內元素的移動,所以效率也是比add(E e)方法還要低。

remove(int index):在指定索引位置刪除元素,就是把index位置後的所有元素都往前移一個大小,也是涉及到表內元素的移動,效率也是很低的。

remove(Object o):刪除指定的元素,也就需要查找出該元素在表中出現第一次的位置,查找是用到順序一個一個進行匹配的方法,找出後就把該元素後面的所有元素往前移一個大小。該方法涉及到順序查找和表內元素移動,比remove(int index)方法更低效。

set(int index,E element):替換表中索引為index的元素值,返回被替換的值,直接用下標索引訪問元素,所以效率非常高。

get(int index):獲取索引為index的元素,直接用下標索引訪問,所以效率也是非常高。

indexOf(Object o):獲取元素的索引號,也就是需要查找,雖然用到了順序查找法,但效率還是比較高的。

LinkedList:擅長於對元素的插入和刪除操作,但對於隨機訪問元素比較慢。該類的實現是以雙向鏈表的數據結構為基礎的,所以是比較消耗內存的,但它的特定集比ArrayList更大。雙向鏈表,每個節點都有三個域,兩個域是存放前後節點的內存地址引用的,一個域是存放數據元素的。在LinkedList類中,有一個叫Entry的內部類,是private的,裡面三個屬性,分別是element、next和previous,分別對應了雙向鏈表中的三個域,在ArrayList類中每實例化一個Entry就生成一個節點。下面看看它的核心方法:add(E e):把元素插入到鏈表末尾,首先要實例化一個節點,新節點previous域存放鏈表中最後一個節點地址,next域存放鏈表中第一個節點地址,element域存放元素值,鏈表中最後一個節點的next域存放新節點的地址,第一個元素的previous域存放新節點的地址,這樣這個元素就插入到該鏈表中去了,沒有涉及到復雜的操作,所以是非常高效的。

add(int index,E element):在index位置插入元素,這就需要先查找到該位置。查到後,這裡就把查到的節點的前一個節點叫為A,實例化新的節點為B,查到index的節點為C.B的next域等於A的next值(也就是C的內存地址),B的previous域等於C的previous值(也就是A的內存地址),B的element域存放元素值,然後把A的next域和C的previous域都等於B的內存地址。這樣也就把元素插入到鏈表的index位置中去了,但涉及到了查詢,所以效率雖然高,但也沒有add(E e)那麼高。

remove(int index):刪除在index位置的元素,首先也是要找到該位置的節點。然後把該節點的下一個節點(也就是該節點next域的內存地址那個節點)的previous值等於該節點的previous值,該節點的上一個節點(也就是該節點previous域的內存地址那個節點)的next值等於該節點的next值。這樣就把該節點從這條鏈表刪除了,過程中雖然涉及到了查找,但沒有涉及到像ArrayList類中的remove方法要移動表中元素,所以該方法的效率還是很高的。

remove(Object o):刪除在鏈表中第一個元素為o的節點,也是需要查找到該節點,然後就跟remove(int index)思路一樣把元素刪除,所以效率也是很高的。

set(int index,E element):把在鏈表中第index個元素值改為element,這也需要找到該節點來修改元素值,但涉及到了查找節點,ArrayList中的set方法就不用查找就可以修改,所以相對於ArrayList中的set方法,LinkedList方法set方法效率就沒那麼高了。

get(int index):獲取第index位置的元素值,也是要找到該節點,所以就也沒ArrayList中的get方法那麼高效率了,因為該方法需要查找鏈表。

indexOf(Object o):獲取該鏈表中第一o元素的位置,也是要查找鏈表,但ArrayList中的indexOf方法也是需要查找的,所以這兩個類的indexOf的效率都差不多。

所以,在編程中,如果要進行大量的隨機訪問,就使用ArrayList;如果要經常從表中插入或刪除元素的就應該使用LinkedList.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved