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介面的類:
每天學習一點點,每天進步一點點。