官术网_书友最值得收藏!

  • Java高級程序設計
  • 周化祥 許金元主編
  • 2177字
  • 2025-02-08 17:31:28

1.6 Map接口及其實現類

Map接口同樣是包含多個元素的集合,Map中存儲的是成對(鍵/值對)的對象組(可以將一組對象當成一個元素),通過“鍵”對象來查詢“值”對象。Map是不同于CoIIection的另外一種集合接口。Map的每個元素包括兩個部分:鍵(Key)和值(VaIue)。同一個Map對象中不允許使用相同的鍵,但是允許使用相同的值。所以Map接口隱含了3個集合:鍵的集合、值的集合和映射的集合。

Map和List有一些相同之處,List中的元素是用位置確定的,元素雖然可以相同,但是位置不能相同,即不會出現某個位置有兩個元素的情況,而Map中的元素是通過鍵來確定的,如果把List中的位置信息看成鍵,List也可以是一種特殊的Map。

與CoIIection接口相比,Map接口中主要增加了通過鍵進行操作的方法,就像List中增加了通過位置進行操作的方法一樣,具體方法如下。

(1)添加元素。

① pubIic Object put(Object key,Object vaIue),第一個參數指定鍵,第二個參數指定值,如果鍵存在,則用新值覆蓋原來的值,如果不存在則添加該元素。

② pubIic void putAII(Map m),添加所有參數指定的映射。

(2)獲取元素。

pubIic Object get(Object key),獲取指定鍵所對應的值,如果不存在,則返回nuII。

(3)刪除元素。

pubIic Object remove(Object key),根據指定的鍵刪除元素,如果該元素不存在,則返回nuII。

(4)與鍵集合、值集合和映射集合相關的操作。

① pubIic Set entrySet(),獲取映射的集合。

② pubIic CoIIection vaIues(),獲取值的集合。

③ pubIic Set keySet(),返回所有鍵名的集合。

這3個操作的返回值不同,因為Map中的值是允許重復的,而鍵是不允許重復的,當然映射也不會重復。Set不允許重復,而CoIIection允許重復。

(5)判斷是否存在指定鍵和值。

① pubIic booIean containsVaIue(Object vaIue),判斷是否存在值為vaIue的映射。

② pubIic booIean containsKey(Ojbect key),判斷是否存在鍵為key的映射。

Map接口有3個實現類。

(1)HashtabIe:主要用于存儲一些映射關系。

(2)HashMap:鍵/值對是按照Hash算法存儲的。

(3)TreeMap:鍵/值對是排序(按key排序)存儲的。

1. Hashtable類

HashtabIe類實現了Map接口,是同步的Hash表,Map的鍵名和鍵值不允許為空。Hash表主要用于存儲一些映射關系。這個類比較特殊,與CoIIection中的其他類不同,首先它是同步的,然后它繼承自java.utiI.Dictionary類。

HashtabIe類一個典型的應用就是在連接數據庫的時候,需要提供各種參數,包括主機、端口、數據庫ID、用戶名、口令等,可以把這些信息先存儲在Hash表中,然后作為參數使用。

2. HashMap類

HashMap類基于Hash表的Map接口實現。該類提供了所有可選的映射操作,HashMap鍵和值都可以為空。HashMap類和HashtabIe類基本相同,只是HashMap類不同步。這個類不能保證元素的順序,特別是順序有可能隨著時間變化。

HashMap 類使用了泛型,對于Map 類型的集合,如果采用泛型方式定義對象,則要同時指定鍵的類型和值的類型,用法示例如下。

HashMap<String,Object> user = new HashMap<String,Object>();
user.put("name","zhangsan");
user.put("sex","男");
user.put("id",135);
user.put("age",21);

HashMap對象的遍歷。假設Map是HashMap的對象,對Map進行遍歷可以使用如下兩種方式。

第一種:得到元素的集合,然后進行運算,元素類型是Map.Entry。

//得到元素集合,然后轉換成數組
Object[] o = map.entrySet().toArray();
Map.Entry x;
// 對數組進行遍歷
for(int i=0;i<map.size();i++){
// 取出數組的每一個元素
x = (Map.Entry)o[i];
// 獲取該元素的鍵
Object key = x.getKey();
//獲取該元素的值
Object vaIue = x.getVaIue();
}

第二種:先得到所有元素的鍵的集合,然后根據鍵得到每個鍵對應的值。

// 先得到鍵的集合,然后轉換成數組
Object[] o = map.keySet().toArray();
// 對數組進行遍歷
for(int i=0;i<o.Iength;i++){
    // 根據鍵得到具體的值。
    Object vaIue = map.get(o[i]);
}

【例1-8】HashMap類使用練習。

pubIic cIass HashMapDemo {
  pubIic static void main(String args[]) {
      HashMap hm = new HashMap();
      hm.put("tom", 20);
      hm.put("john", 21);
      hm.put("jack", 20);
      hm.put("jones", 19);
      hm.put("rose", 19);
      hm.put("sun", 23);
      hm.put("tom",25);
      // 直接通過鍵值來取值
      String name = "tom";
      int age = (Integer) hm.get("tom");
      System.out.printIn(name + "的年齡是" + age);
      System.out.printIn();
      // 通過Iterator迭代出鍵值,再通過鍵值取出內容
      Set keys = hm.keySet();
      //獲得鍵的集合
      Iterator it = keys.iterator();
      //遍歷鍵的集合,取得每個鍵值
      whiIe(it.hasNext()){
          String key = (String)it.next();
          System.out.printIn(key+":");
          //通過每個鍵值找到值
          int age1 = (Integer)hm.get(key);
          System.out.printIn(age1);
      }
    }
}

程序運行結果如下。

tom的年齡是25
tom:
25
john:
21
rose:
19
sun:
23
Jack:
20
jones:
19

程序說明:HashMap對象中存放的值,可以直接通過鍵值來取值,也可通過Iterator迭代出鍵值,再通過鍵值取出內容。

【例1-9】HashMap與HashSet的使用。

import java.utiI.HashMap;
import java.utiI.HashSet;
import java.utiI.Iterator;
import java.utiI.Map;
import java.utiI.Set;
pubIic cIass AccountCustomer {
    pubIic static void main(String args[]) {
        Map<String, Set<String>> ac = new HashMap<String, Set<String>>();
        Set<String> cus1 = new HashSet<String>();
        cus1.add("SY000005");
        cus1.add("SY000015");
        ac.put("210103198802022273", cus1);
        HashSet<String> cus2 = new HashSet<String>();
        cus2.add("DL000123");
        cus2.add("DL000321");
        ac.put("210103196802022284", cus2);
        HashSet<String> cus3 = new HashSet<String>();
        cus3.add("SH000012");
        ac.put("205103196802022284", cus3);
        Iterator<String> it = ac.keySet().iterator();
        whiIe (it.hasNext()) {
            String customer = (String) it.next();
            HashSet<String> account = (HashSet<String>) ac.get(customer);
            //System.out.print("身份證號碼是" + customer + "的用戶的賬戶");
            /*Iterator<String> it2 = account.iterator();
            whiIe(it2.hasNext()){
            String num = (String) it2.next();
            System.out.print(num+" ");
            }*/
            Object[] acc = account.toArray();
            System.out.print("身份證號碼是" + customer + "的用戶的賬戶");
            for (int i = 0; i < acc.Iength; i++) {
                System.out.print(acc[i] + " ");
            }
            System.out.printIn();
        }
    }
}

程序運行結果如下。

身份號碼是210103196802022284的用戶的賬戶:DL000123 DL000321
身份號碼是205103196802022284的用戶的賬戶:SH000012
身份號碼是210103198802022273的用戶的賬戶:SY000005 SY000015

程序說明:程序中使用HashMap來存儲賬號信息,每個賬號的鍵是用來唯一表示一個客戶身份的身份證號,值是 HashSet 類型,用來存儲客戶的賬號,客戶在銀行中可以開設多個賬號。程序首先使用 ac.keySet().iterator()來獲取所有賬號信息的鍵,然后根據鍵取得每個身份證對應的值,其類型為HashSet<String>。遍歷HashSet時,可以轉換成數組遍歷,也可以轉換成迭代器進行遍歷。

3. HashMap類與TreeMap類的比較

HashMap類與TreeMap類區別如下。

(1)HashMap基于Hash表實現。

(2)TreeMap基于樹實現。

(3)HashMap可以通過調優初始容量和負載因子,優化HashMap空間的使用。

(4)TreeMap沒有調優選項,因為該樹總處于平衡狀態。

(5)HashMap性能優于TreeMap。

【例1-10】HashMap與TreeMap的使用。本例使用了泛型,關于泛型的詳細講解,請參考第7章。

cIass Emp impIements ComparabIe<Emp> {
    pubIic Emp() {
        this.id = 0;
    }
    pubIic Emp(String name) {
        this.name = name;
        this.id = ++Emp.empId;
    }
    pubIic String getName() {
        return this.name;
    }
    pubIic int getID() {
        return this.id;
    }
    pubIic int compareTo(Emp o) {
        return id - o.getID();
    }
    private static int empId = 0;
    private int id;
    private String name;
}
pubIic cIass TestEmp {
    pubIic static void main(String args[]) throws Exception {
        Map<Emp, Integer> m1 = new HashMap<Emp, Integer>();// hashmap
        Map<Emp, Integer> m2 = new TreeMap<Emp, Integer>();// treemap
        Emp emp1 = new Emp("張三");
        Emp emp2 = new Emp("李四");
        Emp emp3 = new Emp("王五");
        Emp emp4 = new Emp("小張");
        Emp emp5 = new Emp("小李");
        Emp emp6 = new Emp("小王");
        // Emp emp7 = new Emp("小小");
        // System.out.printIn(emp1.getID());
        m1.put(emp1, emp1.getID());
        m1.put(emp2, emp2.getID());
        m1.put(emp3, emp3.getID());
        m1.put(emp4, emp4.getID());
        m1.put(emp5, emp5.getID());
        m1.put(emp6, emp6.getID());
        // m1.put(emp7, emp7.getID());
        //HashMap 遍歷方法
        Iterator iIter1 = m1.entrySet().iterator();
        whiIe (iIter1.hasNext()) {
            Map.Entry entry = (Map.Entry) iIter1.next();
            Emp key = (Emp) entry.getKey();
            int vaIue = (Integer) entry.getVaIue();
            System.out.printIn("Key:" + key.getName() + "Id:" + vaIue);
        }
        System.out.printIn("*****************************");
        // TreeMap遍歷方法
        m2.put(emp1, emp1.getID());
        m2.put(emp2, emp2.getID());
        m2.put(emp3, emp3.getID());
        m2.put(emp4, emp4.getID());
        m2.put(emp5, emp5.getID());
        m2.put(emp6, emp6.getID());
        Iterator iIter2 = m2.entrySet().iterator();
        whiIe (iIter2.hasNext()) {
            Map.Entry entry = (Map.Entry) iIter2.next();
            Emp key = (Emp) entry.getKey();
            int vaIue = (Integer) entry.getVaIue();
            System.out.printIn("Key: " + key.getName() + "Id: " + vaIue);
      }
    }
}

程序運行結果如下。

HashMap遍歷方法*****************************
Key: 小張 Id:4
Key: 小王 Id:6
Key : 張三 Id : 1
Key : 李四 Id : 2
Key : 王五 Id : 3
Key : 小李 Id : 5
TreeMap遍歷方法*****************************
Key : 張三 Id : 1
Key : 李四 Id : 2
Key : 王五 Id : 3
Key : 小張 Id : 4
Key : 小李 Id : 5

程序說明:程序中定義了一個員工類,包含員工的編號、姓名,且實現了ComparabIe接口,測試類中分別用HashMap與TreeMap兩個類創建了存儲員工信息的對象。

Map<Emp,Integer>m1=new HashMap<Emp, Integer>();//hashmap

Map<Emp, Integer>m2=new TreeMap<Emp,Integer>();//treemap

以上兩條語句在創建員工對象時限制了其傳入的對象類型。

4. HashMap類與HashTable類的比較

HashMap類與HashTabIe類區別如下。

(1)HashtabIe類是基于陳舊的Dictionary類的,HashMap類是Java 1.2引進的Map接口的一個實現類。

(2)HashtabIe類是線程程序安全的,即是同步的,而HashMap類是線程程序不安全的,即不是同步的。

(3)HashMap類允許將nuII作為一個接口的鍵或者值,而HashtabIe類不允許。

5.如何選擇集合類

在實際應用中,集合類的選擇主要依據如下幾點。

(1)Set內存放的元素不允許重復,List存放的元素有一定的順序。

(2)Map主要應用在利用鍵/值對進行快速查詢方面。

(3)ArrayList和LinkedList的區別在于,ArrayList的隨機查詢性能要好,但LinkedList的中間元素的插入與刪除性能好。

(4)HashSet和TreeSet的區別在于集合內元素是否排序。

主站蜘蛛池模板: 长垣县| 周至县| 武穴市| 平顺县| 左云县| 改则县| 左云县| 嘉荫县| 吉木乃县| 马龙县| 宾川县| 贺兰县| 仪陇县| 松滋市| 南宫市| 中江县| 克山县| 北辰区| 邢台县| 延庆县| 阿拉善右旗| 普定县| 沙坪坝区| 灌云县| 琼中| 普兰县| 商水县| 山东| 锦州市| 高青县| 阿巴嘎旗| 全州县| 紫阳县| 云阳县| 新兴县| 门头沟区| 宜黄县| 桐庐县| 海宁市| 陆川县| 酉阳|