Map集合概述
-
首先對比一下Map接口和Collection接口
// Collection集合,有一個泛型<E> public interface Collection<E> extends Iterable<E> { ... } // Map集合,有兩個泛型<K, V> public interface Map<K,V> { ... } -
在Collection集合中,E映射的是值的類型。在Map集合中,K映射的是鍵的類型,V映射的是值的類型。
-
簡單的說,Map集合是一個將鍵(Key)映射到值(Value)的對象。且一個映射不能包含重復的鍵;每個鍵只能映射到一個值。
-
Map接口提供三種collection視圖,允許以Key集、Value集、Key-Value映射關系的形式查看某個映射的內容。映射順序定義為迭代器在映射的collection視圖上返回其元素的順序。
那什么是映射呢?在生活中,我們常常會看到這樣的一種集合:賬號——密碼、IP地址——主機名、系統用戶名——系統用戶對象等。像這種一一對應的關系,就叫做映射。在Java中,Map類就是如此,專門用來存放這種對象關系的對象。
Map集合與Collection集合的區別
- collection中的集合,元素是孤立存在的(單身狗),向集合中存儲元素采用一個個元素的方式存儲。
- map中的集合,元素是成對存在的(情侶、夫妻),每個元素由鍵(key)與值(value)兩個部分組成,通過鍵可以找到其所對應的值。
- collection中的集合成為單列集合,map中的集合稱為雙列集合。
- Collection接口的底層是由哈希表或哈希表+鏈表實現的。
- Map接口的底層是由哈希表和鏈接列表實現的
簡單總結一下Map集合的特點
- Map集合是一個雙列集合,一個元素包含兩個值(一個key,一個value)。
- Map集合中的元素,key和value的數據類型可以相同,也可以不同。
- Map集合中的元素,key是不允許重復的, value是可以重復的。
- Map集合中的元素,key和 value是一一對應的。
Map接口常用的方法
public V put(K key, V value)
// 把指定的鍵與指定的值添加到Map集合中。
public V remove(Object key)
// 把指定的鍵所對應的鍵值對元素在Map集合中刪除,返回被刪除元素的值
public V get(Object key)
// 根據指定的鍵,在Map集合中獲取對應的值。
boolean containsKey(Object key)
// 判斷集合中是否包含指定的鍵。
public Set<K> keySet()
// 獲取Map集合中所有的鍵,存儲到Set集合中。
public Set<Map. Entry<K,V> entrySet()
// 獲取到Map集合中所有的鍵值對對象的集合(Set集合)。
put()方法
- 作用:把指定的鍵與指定的值添加到Map集合中。
- 注意:
- 當要添加的key不存在的時候,調用put方法后,map集合中會添加新的
,添加成功會返回null。 - 當要添加的key存在的時候,調用put方法后,會使用新的Value替換map集合中舊的Value,替換成功會返回舊的Value。
- 當要添加的key不存在的時候,調用put方法后,map集合中會添加新的
舉例
-
例子1:
import java.util.HashMap; import java.util.Map; public class DemoMapPut { public static void main(String[] args) { // 用多態的形式,創建一個hashMap集合,集合長度為16 Map<String, String> hashMap = new HashMap<>(16); // 使用Map接口的特有方法put方法,向集合中添加<key-value> String return0 = hashMap.put("楊過", "小龍女"); String return1 = hashMap.put("過兒", "姑姑"); System.out.println("返回值0:" + return0); System.out.println("返回值1:" + return1); System.out.println("Map集合:" + hashMap); } } -
輸出結果:
返回值0:null 返回值1:null Map集合:{楊過=小龍女, 過兒=姑姑} -
例子2:
import java.util.HashMap; import java.util.Map; public class Demo02MapPut { public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(16); String return0 = hashMap.put("楊過", "小龍女"); String return1 = hashMap.put("楊過", "姑姑"); System.out.println("返回值0:" + return0); System.out.println("返回值1:" + return1); System.out.println("Map集合:" + hashMap); } } -
輸出結果:
返回值0:null 返回值1:小龍女 Map集合:{楊過=姑姑}
remove()方法
-
作用:把指定的鍵所對應的鍵值對元素在Map集合中刪除,返回被刪除元素的值。
-
注意:
- key存在,刪除對應元素,並返回被刪除的值
- key不存在,返回null
-
例子:
import java.util.HashMap; import java.util.Map; public class Demo01MapRemove { public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(16); hashMap.put("key0", "value0"); hashMap.put("key1", "value1"); hashMap.put("key2", "value2"); System.out.println("沒有調用remove方法前的Map集合:" + hashMap); String return0 = hashMap.remove("key0"); String return1 = hashMap.remove("key666"); System.out.println("返回值0:" + return0); System.out.println("返回值1:" + return1); System.out.println("調用remove方法后的Map集合:" + hashMap); } } -
輸出結果:
沒有調用remove方法前的Map集合:{key1=value1, key2=value2, key0=value0} 返回值0:value0 返回值1:null 調用remove方法后的Map集合:{key1=value1, key2=value2}
get()方法
-
作用:根據指定的鍵,在Map集合中獲取對應的值。
-
注意:
- key存在,並返回對應Value值
- key不存在,返回null
-
例子:
import java.util.HashMap; import java.util.Map; public class Demo01MapGet { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("Aa", 18); hashMap.put("Bb", 20); System.out.println("key是'Aa'對應的Value是:" + hashMap.get("Aa")); System.out.println("key是'BB'對應的Value是:" +hashMap.get("BB")); } } -
輸出結果:
key是'Aa'對應的Value是:18 key是'BB'對應的Value是:null
containsKey()方法
-
作用:判斷集合中是否包含指定的鍵。
-
返回值:
- key存在的情況下,返回true
- key不存在的情況下,返回false
-
例子:
import java.util.HashMap; import java.util.Map; public class Demo01MapContainsKey { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 100); hashMap.put("k2", 200); System.out.println("hashMap集合:" + hashMap); boolean response1 = hashMap.containsKey("k1"); boolean response2 = hashMap.containsKey("k999"); System.out.println("是否存在鍵值為'k1'的元素:" + response1); System.out.println("是否存在鍵值為'k999'的元素:" + response2); } } -
輸出結果:
hashMap集合:{k1=100, k2=200} 是否存在鍵值為'k1'的元素:true 是否存在鍵值為'k999'的元素:false
keySet()方法
-
作用:獲取Map集合中所有的鍵,存儲到Set集合中。
-
返回值:返回Map集合中所有的Key的一個集合對象。
-
例子:
import java.util.Map; import java.util.HashMap; import java.util.Set; public class Demo01MapKeySet { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 1); hashMap.put("k2", 2); hashMap.put("k3", 3); hashMap.put("k4", 4); hashMap.put("k5", 5); hashMap.put("k6", 6); System.out.println("hashMap:" + hashMap); // 使用keySet()方法,獲取Map集合中所有的鍵,存儲到Set集合中。 Set<String> set = hashMap.keySet(); // 輸出set集合 System.out.println("set:" + set); } } -
輸出結果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} set:[k1, k2, k3, k4, k5, k6]
entrySet()方法
-
作用:獲取到Map集合中所有的鍵值對對象的集合(Set集合)。
-
返回值:返回值是一個key-value的Set集合對象
-
注意:由於Map集合中有兩個泛型(K, V),Set集合中只有一個泛型,所以不能直接賦值給Set對象,但可以通過Map.Entry的方式賦值給Set對象
-
如:

拋出錯誤:

-
或者又如:

拋出錯誤:

-
賦值給Set集合對象:


-
entrySet方法舉例:
import java.util.HashMap; import java.util.Map; public class Demo01MapEntrySet { public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(16); hashMap.put("k1", "1"); hashMap.put("k2", "2"); hashMap.put("k3", "3"); hashMap.put("k4", "4"); hashMap.put("k5", "5"); hashMap.put("k6", "6"); System.out.println("hashMap:" + hashMap); // 調用entrySet方法,獲取到Map集合中所有的鍵值對對象的集合 System.out.println("鍵值對對象的集合:" + hashMap.entrySet()); } } -
輸出結果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} 鍵值對對象的集合:[k1=1, k2=2, k3=3, k4=4, k5=5, k6=6]
Map集合遍歷鍵(key)的方式找值(Value)
-
通過Map集合的keySet()方法,獲取Map集合中所有的Key,存儲到Set集合中
-
遍歷Set集合,獲取每個Key所對應的Value
-
舉例:
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Demo01MapIteratorKey { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 1); hashMap.put("k2", 2); hashMap.put("k3", 3); hashMap.put("k4", 4); hashMap.put("k5", 5); hashMap.put("k6", 6); System.out.println("hashMap:" + hashMap); Set<String> sKey = hashMap.keySet(); // 獲取Set集合的迭代器對象,並遍歷該迭代器對象 Iterator<String> ite = sKey.iterator(); while (ite.hasNext()) { // 通過迭代器對象中的每一個值(Map集合中的鍵),獲取key-value System.out.println( "Key:" + ite.next() + " Value:" + hashMap.get(ite.next()) ); } } } -
輸出結果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} Key:k1 Value:2 Key:k3 Value:4 Key:k5 Value:6
Map集合遍歷鍵值對方式
例子理解:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo01MapIteratorKeyValue {
public static void main(String[] args) {
Map<String, Integer> hashMap = new HashMap<>(16);
hashMap.put("k1", 1);
hashMap.put("k2", 2);
hashMap.put("k3", 3);
hashMap.put("k4", 4);
hashMap.put("k5", 5);
hashMap.put("k6", 6);
System.out.println("hashMap:" + hashMap);
Set<Map.Entry<String, Integer>> keyValue = hashMap.entrySet();
// 獲取Set集合的迭代器對象,並遍歷該迭代器對象
Iterator<Map.Entry<String, Integer>> ite = keyValue.iterator();
while (ite.hasNext()) {
// 通過Entry對象的getKey()和getValue()方法,獲取Key和Value
Map.Entry<String, Integer> kv = ite.next();
System.out.println(
"Key:" + kv.getKey() +
" Value:" + kv.getValue()
);
}
}
}
輸出結果:
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6}
Key:k1 Value:1
Key:k2 Value:2
Key:k3 Value:3
Key:k4 Value:4
Key:k5 Value:5
Key:k6 Value:6
HashMap存儲自定義類型的鍵值
注意:Map集合,要保證Key是唯一的。作為Key的元素,必須重寫hashCode()方法和equals()方法,才能保證Key的唯一性
代碼理解
-
創建一個Student類,用左Map中Key的數據類型:
public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } -
創建兩個方法:
- 方法1使用<String, String>為<key, value>的數據類型
- 方法2使用<Student, String>為<key, value>的數據類型
import java.util.HashMap; import java.util.Map; public class MapRepeat { /** * String類型已經重寫了hashCode()方法和equals()方法 * 可以保證key唯一 */ public static void method01() { Map<String, String> map = new HashMap<>(16); map.put("k1", "v1"); map.put("k2", "v2"); map.put("k3", "v3"); map.put("k4", "v4"); map.put("k1", "v5"); System.out.println(map); } /** * Student類型沒有重寫hashCode()方法和equals()方法 * 不能保證key唯一 */ public static void method02() { Map<Student, String> map = new HashMap<>(16); map.put(new Student("學生1", 22), "v1"); map.put(new Student("學生2", 18), "v2"); map.put(new Student("學生3", 19), "v3"); map.put(new Student("學生4", 21), "v4"); map.put(new Student("學生1", 22), "v5"); System.out.println(map); } } -
比較這兩個方法:
public class Demo01MapRepeat { public static void main(String[] args) { // Map<String, String>,String類已經重寫了hashCode()方法和equals()方法 MapRepeat.method01(); // Map<Student, String>,Student類沒有重寫了hashCode()方法和equals()方法 MapRepeat.method02(); } } -
輸出結果:
{k1=v5, k2=v2, k3=v3, k4=v4} {Student{name='學生1', age=22}=v1, Student{name='學生1', age=22}=v5, Student{name='學生2', age=18}=v2, Student{name='學生4', age=21}=v4, Student{name='學生3', age=19}=v3}
可以看到,方法1輸出的集合,並沒有重復的Key,而方法2輸出的集合存在沖的的Key。其中重復的Key是Student{name='學生1', age=22}
在Student類中重寫hashCode()方法和equals()方法
import java.util.Objects;
public class Student {
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
那么對MapRepeat.method02()測試,輸出結果則是:
{Student{name='學生4', age=21}=v4, Student{name='學生2', age=18}=v2, Student{name='學生3', age=19}=v3, Student{name='學生1', age=22}=v5}
可以看出,與沒有重寫hashCode()方法和equals()方法前相比,重寫后,不存在重復的key了。
LinkedHashMap集合簡單了解
-
說明:
- LinkedHashMap類是HashMap的子類
- LinkedHashMap底層采用的是哈希表+鏈表結構,LinkedHashMap集合是有存取順序的集合,而其父類HashMap是沒有存取順序的集合
-
例子:
import java.util.Map; import java.util.HashMap; import java.util.LinkedHashMap; public class DemoLinkedHashMap { public static void main(String[] args) { // 無序Map集合:HashMap Map<Integer, Integer> hashMap = new HashMap<>(16); hashMap.put(1, 200); hashMap.put(3, 400); hashMap.put(5, 600); hashMap.put(2, 100); hashMap.put(4, 300); hashMap.put(6, 500); System.out.println(hashMap); // 有序Map集合:LinkedHashMap Map<Integer, Integer> linked = new LinkedHashMap<>(16); linked.put(1, 200); linked.put(3, 400); linked.put(5, 600); linked.put(2, 100); linked.put(4, 300); linked.put(6, 500); System.out.println(linked); } } -
輸出結果:
{1=200, 2=100, 3=400, 4=300, 5=600, 6=500} {1=200, 3=400, 5=600, 2=100, 4=300, 6=500}
Hashtable集合的簡單了解
說明
- java.utiL.Hashtable<k, v>集合 implements Map<K,V>接口Hashtable
- 底層也是一個哈希表,是一個線程安全的集合,是單線程集合,速度慢
- HashMap:底層是一個哈希表,是一個線程不安全的集合,是多線程的集合,速度快
- ArrayList集合、LinkedList集合、HashSet集合、HashMap集合等:可以存儲null值【null鍵】
- Hashtable集合,不能存儲null值,null鍵
- Hashtable和Vector集合一樣,在jdk1.2版本之后被更先進的集合( HashMap、 ArrayList)取代了
- Hashtable的子類 Properties依然活躍在歷史舞台
- Properties集合是一個唯一和I0流相結合的集合
Hashtable傳入null,拋出錯誤

例子
import java.util.HashMap;
import java.util.Hashtable;
public class DemoHashTable {
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<>(16);
hashMap.put(null, null);
hashMap.put(null, "A");
hashMap.put("A", null);
hashMap.put("B", "B");
System.out.println("hashMap:" + hashMap);
Hashtable<String, String> hashtable = new Hashtable<>(16);
// Hashtable集合,key和value都不能是null
// 如果傳入空值,會拋出錯誤:空指針異常(NullPointerException)
// hashtable.put(null, null);
// hashtable.put(null, "A");
// hashtable.put("A", null);
hashtable.put("B", "B");
System.out.println("hashtable:" + hashtable);
}
}
輸出結果:
hashMap:{null=A, A=null, B=B}
hashtable:{B=B}
