1. 程式人生 > >java中Map類有什麼作用,具體怎麼用呢

java中Map類有什麼作用,具體怎麼用呢

Map以按鍵/數值對的形式儲存資料,和陣列非常相似,在陣列中存在的索引,它們本身也是物件。   
     Map的介面   
     Map---實現Map   
     Map.Entry--Map的內部類,描述Map中的按鍵/數值對。   
     SortedMap---擴充套件Map,使按鍵保持升序排列   
    
     關於怎麼使用,一般是選擇Map的子類,而不直接用Map類。   
     下面以HashMap為例。   
     public      static      void      main(String      args[])   
     {   
         HashMap      hashmap      =      new      HashMap();   
         hashmap.put("Item0",      "Value0");   
         hashmap.put("Item1",      "Value1");   
         hashmap.put("Item2",      "Value2");   
         hashmap.put("Item3",      "Value3");   
         Set      set      =      hashmap.entrySet();   
         Iterator      iterator      =      set.iterator();   
         while      (iterator.hasNext()   
       {   
           Map.Entry      mapentry      =      (Map.Entry)      iterator.next();   
           System.out.println(mapentry.getkey()      +      "/"      +      mapentry.getValue());   
       }   
     }   
     注意,這裡Map的按鍵必須是唯一的,比如說不能有兩個按鍵都為null。   
     如果用過它,就會知道它的用處了。

資料:

java.util 中的集合類包含 Java 中某些最常用的類。 最常用的集合類是 List 和 Map。

 List 的具體實現包括 ArrayList 和 Vector,它們是可變大小的列表,比較適合構建、儲存和操作任何型別物件的元素列表。 List 適用於按數值索引訪問元素的情形。

Map 提供了一個更通用的元素儲存方法。 Map 集合類用於儲存元素對(稱作“鍵”和“值”),其中每個鍵對映到一個值。 從概念上而言,您可以將 List 看作是具有數值鍵的 Map。 而實際上,除了 List 和 Map 都在定義 java.util 中外,兩者並沒有直接的聯絡。本文將著重介紹核心 Java 發行套件中附帶的 Map,同時還將介紹如何採用或實現更適用於您應用程式特定資料的專用 Map。

瞭解 Map 介面和方法

Java 核心類中有很多預定義的 Map 類。 在介紹具體實現之前,我們先介紹一下 Map 介面本身,以便了解所有實現的共同點。 Map 介面定義了四種類型的方法,每個 Map 都包含這些方法。 下面,我們從兩個普通的方法(表 1)開始對這些方法加以介紹。

表 1: 覆蓋的方法。 我們將這 Object 的這兩個方法覆蓋,以正確比較 Map 物件的等價性。

equals(Object o) 比較指定物件與此 Map 的等價性
hashCode() 返回此 Map 的雜湊碼

Map 構建

Map 定義了幾個用於插入和刪除元素的變換方法(表 2)。

表 2: Map 更新方法: 可以更改 Map 內容。

clear() 從 Map 中刪除所有對映
remove(Object key) 從 Map 中刪除鍵和關聯的值
put(Object key, Object value) 將指定值與指定鍵相關聯
clear() 從 Map 中刪除所有對映
putAll(Map t) 將指定 Map 中的所有映射覆制到此 map

儘管您可能注意到,縱然假設忽略構建一個需要傳遞給 putAll() 的 Map 的開銷,使用 putAll() 通常也並不比使用大量的 put() 呼叫更有效率,但 putAll() 的存在一點也不稀奇。 這是因為,putAll() 除了迭代 put() 所執行的將每個鍵值對新增到 Map 的演算法以外,還需要迭代所傳遞的 Map 的元素。 但應注意,putAll() 在新增所有元素之前可以正確調整 Map 的大小,因此如果您未親自調整 Map 的大小(我們將對此進行簡單介紹),則 putAll() 可能比預期的更有效。

檢視 Map

迭代 Map 中的元素不存在直接了當的方法。 如果要查詢某個 Map 以瞭解其哪些元素滿足特定查詢,或如果要迭代其所有元素(無論原因如何),則您首先需要獲取該 Map 的“檢視”。 有三種可能的檢視(參見表 3

  • 所有鍵值對 — 參見 entrySet()
  • 所有鍵 — 參見 keySet()
  • 所有值 — 參見 values()

前兩個檢視均返回 Set 物件,第三個檢視返回 Collection 物件。 就這兩種情況而言,問題到這裡並沒有結束,這是因為您無法直接迭代 Collection 物件或 Set 物件。要進行迭代,您必須獲得一個 Iterator 物件。 因此,要迭代 Map 的元素,必須進行比較煩瑣的編碼

Iterator keyValuePairs = aMap.entrySet().iterator();Iterator keys = aMap.keySet().iterator();Iterator values = aMap.values().iterator();

值得注意的是,這些物件(Set、Collection 和 Iterator)實際上是基礎 Map 的檢視,而不是包含所有元素的副本。 這使它們的使用效率很高。 另一方面,Collection 或 Set 物件的 toArray() 方法卻建立包含 Map 所有元素的陣列物件,因此除了確實需要使用陣列中元素的情形外,其效率並不高。

我運行了一個小測試(隨附檔案中的 Test1),該測試使用了 HashMap,並使用以下兩種方法對迭代 Map 元素的開銷進行了比較:

int mapsize = aMap.size();Iterator keyValuePairs1 = aMap.entrySet().iterator();for (int i = 0; i < mapsize; i++){    Map.Entry entry = (Map.Entry) keyValuePairs1.next();    Object key = entry.getKey();    Object value = entry.getValue();    ...}Object[] keyValuePairs2 = aMap.entrySet().toArray();for (int i = 0; i < rem; i++) {{    Map.Entry entry = (Map.Entry) keyValuePairs2[i];    Object key = entry.getKey();
Profilers in Oracle JDeveloper

Oracle JDeveloper 包含一個嵌入的監測器,它測量記憶體和執行時間,使您能夠快速識別程式碼中的瓶頸。 我曾使用 Jdeveloper 的執行監測器監測 HashMap 的 containsKey() 和 containsValue() 方法,並很快發現 containsKey() 方法的速度比 containsValue() 方法慢很多(實際上要慢幾個數量級!)。 (參見圖 1圖 2,以及隨附檔案中的 Test2 類)。

    Object value = entry.getValue();    ...}

此測試使用了兩種測量方法: 一種是測量迭代元素的時間,另一種測量使用 toArray 呼叫建立陣列的其他開銷。 第一種方法(忽略建立陣列所需的時間)表明,使用已從 toArray 呼叫中建立的陣列迭代元素的速度要比使用 Iterator 的速度大約快 30%-60%。 但如果將使用 toArray 方法建立陣列的開銷包含在內,則使用 Iterator 實際上要快 10%-20%。 因此,如果由於某種原因要建立一個集合元素的陣列而非迭代這些元素,則應使用該陣列迭代元素。 但如果您不需要此中間陣列,則不要建立它,而是使用 Iterator 迭代元素。

表 3: 返回檢視的 Map 方法: 使用這些方法返回的物件,您可以遍歷 Map 的元素,還可以刪除 Map 中的元素。

entrySet() 返回 Map 中所包含對映的 Set 檢視。 Set 中的每個元素都是一個 Map.Entry 物件,可以使用 getKey() 和 getValue() 方法(還有一個 setValue() 方法)訪問後者的鍵元素和值元素
keySet() 返回 Map 中所包含鍵的 Set 檢視。 刪除 Set 中的元素還將刪除 Map 中相應的對映(鍵和值)
values() 返回 map 中所包含值的 Collection 檢視。 刪除 Collection 中的元素還將刪除 Map 中相應的對映(鍵和值)

訪問元素

表 4 中列出了 Map 訪問方法。Map 通常適合按鍵(而非按值)進行訪問。 Map 定義中沒有規定這肯定是真的,但通常您可以期望這是真的。 例如,您可以期望 containsKey() 方法與 get() 方法一樣快。 另一方面,containsValue() 方法很可能需要掃描 Map 中的值,因此它的速度可能比較慢。

表 4: Map 訪問和測試方法: 這些方法檢索有關 Map 內容的資訊但不更改 Map 內容。

get(Object key) 返回與指定鍵關聯的值
containsKey(Object key) 如果 Map 包含指定鍵的對映,則返回 true
containsValue(Object value) 如果此 Map 將一個或多個鍵對映到指定值,則返回 true
isEmpty() 如果 Map 不包含鍵-值對映,則返回 true
size() 返回 Map 中的鍵-值對映的數目

對使用 containsKey() 和 containsValue() 遍歷 HashMap 中所有元素所需時間的測試表明,containsValue() 所需的時間要長很多。 實際上要長几個數量級! (參見圖 1圖 2,以及隨附檔案中的 Test2)。 因此,如果 containsValue() 是應用程式中的效能問題,它將很快顯現出來,並可以通過監測您的應用程式輕鬆地將其識別。 這種情況下,我相信您能夠想出一個有效的替換方法來實現 containsValue() 提供的等效功能。 但如果想不出辦法,則一個可行的解決方案是再建立一個 Map,並將第一個 Map 的所有值作為鍵。 這樣,第一個 Map 上的 containsValue() 將成為第二個 Map 上更有效的 containsKey()。