最基本上Collection Framework就如圖所示:
Java Collection Framework常用interface |
就這樣嗎?
就這樣。
多麼抽像的敘述啊。沒錯,如果光是這樣的敘述,確實是太「抽像」,而這也是物件導向的一個特色─抽像化。在Collection Framework裡,Collection 這個類別是位於相當高層的類別,除了「很多東西在一塊」這樣的描述可以定義Collection外,其他的描述或定義都交由子類別去決定。不過別忘了,在Java裡,抽像類別是無法產生實體物件(instance),必需要有實作(implement)的類別才可以產生 instance,所以我們在使用的時候,不會直接使用這些 抽像化的類別,而是使用相對應的實作類別來產生instance。
(PS: 其實Collection不是一個抽像類別(abstract class) 或是 class,而是一個 interface,不過在這裡先暫時不用區分的那麼清楚,總而言之,他就是一個定義不是那麼清楚的東西)。
為了介紹常用的一些實作類別,先舉一個情境。比方說我有一個叫做「職業」的Collection,裡面存放著各式各樣的職業:
以程式碼來說,就是這樣:
package taichitech.helloworld.jse; import java.util.HashSet; public class CollectionTest { public static void main(String[] args) { Set執行結果:collection = new HashSet (); collection.add("警察"); collection.add("醫生"); collection.add("公務員"); collection.add("謢士"); collection.add("工人"); System.out.println(collection); } }
[警察, 公務員, 工人, 醫生, 謢士]這段程式碼中,有許多部份會在後面再詳加說明。
我們首先要討論的是繼承Collection的三個 Interface: Set、List與Map。這三種Interface,可以視為是3種資料結構,也各有其不同的特性:
第一個interface是Set,是最簡單的Collection資料結構,就是集合。Set 唯一的限制是不允許重覆的物件存在。實務上常利用這個特性,來過濾重覆的資料。
Set中不允許存放相同的物件 |
- LinkedHashSet
保證裡面元素存放的順序與新增時相同。最適合拿來存放由資料庫中撈取的資料集。 - HashSet
讀取特快,但不保證存放元素的順序。我在上一個程式範例中所使用的 Set 的instance就是HashSet,可以看到執行結果的順序與當初存放的順序是不一樣的。 - TreeSet
依物件大小來決定集合裡面的順序。所以存放於TreeSet中元素必需是(實作) Comparable 的物件。有時候當從自料庫中撈取的資料必需自行排序時,就會用到。
List比Set多了一個索引編號,而且也允許重覆:
List資料結構由0-based 的數字來決定位置,同時也允許重覆的物件存在在相同一個collection中 |
程式碼大概是:
public class CollectionTest {
public static void main(String[] args) { List執行結果大概是:collection = new ArrayList (); collection.add("警察"); collection.add("醫生"); collection.add("醫生"); collection.add("護士"); collection.add("工人"); System.out.println(collection); System.out.println("第一個醫生的位置是:" + (collection.indexOf("醫生"))); } }
[警察, 醫生, 醫生, 護士, 工人] 第一個醫生的位置是:1由於List比Set多了一個索引編號(index),這點也成了要使用List或是Set的一個主要判斷因素。(另一個是資料是否 會/需要 重覆)。例如如果你想取得醫生後面第三個職業是什麼,就可以直接使用索引的方式去取得,好過跑3圈迴圈─好吧,也許3圈不算什麼,如果是30000圈就應該有點差了吧。
System.out.println("第一個醫生後的第30000個職業是:"+ (collection.get(collection.indexOf("醫生") + 30000)));
一般常見的List實作只有 ArrayList,如範例所示。當然因應其他需求,也是還有其他的實作可以用,如LinedList、Stack。
繼承Collection的第三種 interface 是 Map 。
Map的資料結構比較特殊,是一種所謂的「key-value」的資料結構。Key-Value可以把他想像成跟List一樣,也是有一個索引在那裡(就是Key),只是在List中這個索引是數字,而且是從0開始,在Map中這個索引改成物件。通常來說,這個索引是String,不過例外的情況其實也不少,有些情況下,甚至會拿另外一個物件來當做key。(其實String本身也就是一種物件)。
public class CollectionTest { public static void main(String[] args) { Mapcollection = new HashMap (); collection.put("police", "警察"); collection.put("doctor1", "醫生"); collection.put("doctor2", "醫生"); collection.put("worker", "工人"); collection.put("official", "公務員"); System.out.println(collection); System.out.println("Worker的職業是:" + collection.get("worker")); } }
執行結果大概是:
{doctor2=醫生, doctor1=醫生, police=警察, nurse=護士, worker=工人} Worker的職業是:工人Map有幾個特性需要知道:
- key不能重覆
- 沒了… XD
常使用的Map實作比List多:
- HashMap
最基礎的Map。一般也比較常用這個。如同一般的Hash系列,HashMap中元素的存放順序也是隨機的。(如前面的程式範例)。 - TreeMap
Key值可以依照指定的比較方式來進行排序。所以存放於key值的物件必需要是comparable 的。通常這種可以即時排序的資料結構,異動速度都是會打折扣的。TreeMap也不例外。 - LinkedHashMap
與HashMap相同,但保證元素存放的順序與放入的順序相同。
這篇文章對Java Collection Framework做了一點介紹,各位可以在適當的時機使用不同的實作,來達成目的:
- 需要手動對資料庫或是外部資料源進行排序的時候,可以使用Tree系列。搭配Map,更可以對物件的特定屬性做排序。例如以身份證字號為key值,要排序的物件為value,放入TreeMap即可。
- 需要對集合進行批次處理時,可以使用Set─無論是HashSet或是LinkedHashSet。如果在處理時有需要考慮順序,就絕對不能使用HashSet。
- 如果在處理時,需要使用關鍵字、代碼、編號等來取得資料或時,可以考慮使用Map。
沒有留言 :
張貼留言