1. 程式人生 > 實用技巧 >Java 集合 -- Map

Java 集合 -- Map

使用 Map

在 java 集合中,Map 並不在介面 Collection 之中。

介面 Map 的常用實現類有:

  • EnumMap 類

  • HashMap 類

  • TreeMap 類(TreeMap 是介面 SortedMap 的實現類,介面 SortedMap 是 Map 的子介面

  • Properties 類等

Map是一種鍵值(key-value)對映表的資料結構,作用就是能高效通過key快速查詢value(元素)。

Map 的實現類:HashMap

HashMap是一種通過對key計算hashCode(),通過空間換時間的方式,直接定位到value所在的內部陣列的索引,因此,查詢效率非常高。

用HashMap來實現根據name查詢某個Student的程式碼如下:

public class MapMain {
    public static void main(String[] args){
        Student student = new Student("xiao ming",99);
        HashMap<String, Student> map = new HashMap<>();
        // 將 "xiao ming"與Student 例項對映起來
        map.put("xiao ming", student);
        // // 通過key查詢並返回對映的Student例項
        Student target = map.get("xiao ming");

        System.out.println(target == student);
        System.out.println(target.score);
        Student bob = map.get("Bob");
        System.out.println(bob);
    }

    static class Student{ // static 不可或缺
        public String name;
        public int score;

        public Student(String name, int score){
            this.name = name;
            this.score = score;
        }
    }
}

通過上述程式碼可知:Map<K, V>是一種鍵-值對映表,當我們呼叫put(K key, V value)方法時,就把key和value做了對映並放入Map。當我們呼叫V get(K key)時,就可以通過key獲取到對應的value。如果key不存在,則返回null。

和List類似,Map也是一個介面,最常用的實現類是HashMap。

始終牢記:Map中不存在重複的key,因為放入相同的key,只會把原有的key-value對應的value給替換掉。

此外,在一個Map中,雖然key不能重複,但value是可以重複的:

Map<String, Integer> map = new HashMap<>();
map.put("apple", 123);
map.put("pear", 123); // ok

遍歷 Map

對Map來說,要遍歷key可以使用增強for迴圈遍歷Map例項的keySet()方法返回的Set集合,它包含不重複的key的集合:

public static void main(String[] args){
        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 124);
        map.put("pear", 345);
        map.put("banana", 567);
        for (String key:map.keySet()){
            Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
    }

同時遍歷key和value可以使用增強for迴圈遍歷Map物件的entrySet()集合,它包含每一個key-value對映:

public static void main(String[] args){
        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 123);
        map.put("pear", 456);
        map.put("banana", 789);
        for (Map.Entry<String, Integer> entry:map.entrySet()){
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + "=" + value);
        }
    }

Map和List不同的是,Map儲存的是key-value的對映關係,並且,它不保證順序

在遍歷的時候,遍歷的順序既不一定是put()時放入的key的順序,也不一定是key的排序順序。使用Map時,任何依賴順序的邏輯都是不可靠的。

Map 的實現類 EnumMap

如果作為key的物件是enum型別,那麼,還可以使用Java集合庫提供的一種EnumMap,它在內部以一個非常緊湊的陣列儲存value,並且根據enum型別的key直接定位到內部陣列的索引,並不需要計算hashCode(),不但效率最高,而且沒有額外的空間浪費。

我們以DayOfWeek這個列舉型別為例,為它做一個“翻譯”功能:

public class Main {
    public static void main(String[] args) {
        Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);
        map.put(DayOfWeek.MONDAY, "星期一");
        map.put(DayOfWeek.TUESDAY, "星期二");
        map.put(DayOfWeek.WEDNESDAY, "星期三");
        map.put(DayOfWeek.THURSDAY, "星期四");
        map.put(DayOfWeek.FRIDAY, "星期五");
        map.put(DayOfWeek.SATURDAY, "星期六");
        map.put(DayOfWeek.SUNDAY, "星期日");
        System.out.println(map);
     System.out.println(map.get(DayOfWeek.MONDAY));
    }
}
小結
  • 如果Map的key是enum型別,推薦使用EnumMap,既保證速度,也不浪費空間。

  • 使用EnumMap的時候,根據面向抽象程式設計的原則,應持有Map介面。

使用TreeMap

TreeMap 是介面 SortedMap 的實現類,而介面 SortedMap是介面 Map 的子介面。

SortedMap保證遍歷時以Key的順序來進行排序。

例如,放入的Key是"apple"、"pear"、"orange",遍歷的順序一定是"apple"、"orange"、"pear",因為String預設按字母排序:

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>();
        map.put("orange", 1);
        map.put("apple", 2);
        map.put("pear", 3);
        for (String key : map.keySet()) {
            System.out.println(key);
        }
        // apple, orange, pear
    }
}

使用TreeMap時,放入的Key必須實現Comparable介面

String、Integer這些類已經實現了Comparable介面,因此可以直接作為Key使用。作為Value的物件則沒有任何要求。

下圖是已經實現了Comparable介面的類:

每天學習一點點,每天進步一點點。