1. 程式人生 > >【第18天】Java集合(五)---Map介面概述及Map介面實現的HashMap類、SortedMap介面實現的TreeMap類

【第18天】Java集合(五)---Map介面概述及Map介面實現的HashMap類、SortedMap介面實現的TreeMap類

1 Map的通性

在這裡插入圖片描述

       一種鍵值對型別的集合,每次向集合新增一對元素,新增“主鍵Key=值Value”。其中只能在新建時傳入且唯一,傳入後不得修改;值不唯一,可直接修改。

1.1 基本用法與特點

  • 建立Map物件

     HashMap<主鍵型別,值型別> map = new HashMap<>();
     TreeMap<主鍵型別,值型別> map = new TreeMap<>();
    
  • 新增元素

     map.put(主鍵,值);
     map1.putAll(map2);
    
  • 得到集合的大小

     map.size();
    
  • 根據主鍵得到值物件

     map.get(主鍵); -> 值
    
  • 判斷集合裡是否出現指定的主鍵物件

     map.containsKey(主鍵);
    
  • 判斷集合裡是否出現指定的值物件

     map.containsValue(值);
    
  • 根據主鍵刪除元素

     map.remove(主鍵);
    
  • 若想快速判斷Map中某個鍵/值是否存在,要善用contains()方法。根據類中定義好的equals()方法,檢視是否存在,可以直接返回boolean值。同樣使用remove(主鍵)時,也可以通過equals()方法定製刪除主鍵的規則。

1.2 遍歷

姓名 得分
  • 通過Map集合得到所有的主鍵物件(主鍵物件是唯一且無序的,故使用Set來接收即可)能獲取到的是:
姓名
	Set<主鍵> set = map.keySet();

得到主鍵的同時,主鍵是唯一的,可以根據主鍵得到值物件:map.get(主鍵),只能根據主鍵得到對應的值物件而不能改。

  • 通過Map集合得到所有的值物件 (主鍵物件是不唯一且無序的,故只能使用Collection來接收),能獲取到的是:
得分
	Collection<值> coll = map.values();

無法根據值得到對應的主鍵,因為值是不唯一的,只能將值取出。

  • 通過Map集合得到所有記錄的主鍵和值且可以對值進行修改

      Set<Map.Entry<主鍵,值>> set = map.entrySet();
      對set遍歷可以獲取到每一條記錄的主鍵和值
      通過記錄得到主鍵物件:記錄.getKey()
      通過記錄得到值物件:記錄.getValue()
      通過記錄修改值物件:記錄.setValue(XXX)
    

能獲取到的是一條一條的:

姓名 得分
//將Eric的成績 + 20分
import java.util.*;
public class Test{
	public static void main(String[] args){
		HashMap<String,Integer> map = new HashMap<>();
		//新增元素:
		map.put("Allen",455);
		map.put("Eric",122);
		map.put("Cindy",600);
		
		//通過Map集合得到一條記錄 -> [主鍵,值]
		Set<Map.Entry<String,Integer>> set = map.entrySet();
		
		//通過對集合每一條記錄遍歷,得到x -> 即集合裡面的每一條記錄
		for(Map.Entry<String,Integer> x : set){
			
			//通過記錄得到主鍵物件
			String name = x.getKey();
			//通過記錄得到值物件
			Integer score = x.getValue();
			
			if(name.equals("Eric")){
				x.setValue(score + 20);
			}
		}
		System.out.println(set);//--->[Cindy=122, Allen=455, Eric=620]
		System.out.println(map);//--->[Cindy=122, Allen=455, Eric=620]
	}
}
  • 因Map是一個鍵值對,當單獨取值key或value時,不要對其進行修改,只作為一個遍歷查詢的簡便方法。對單獨取值得到的集合進行add()操作會報UnsupportOperationException。但可以對Set型別的主鍵集合中元素進行刪除,進而Map中整個元素被刪除,因為其具有唯一性。

  • 主鍵不能直接修改,若修改需要先remove(主鍵)之前的,再put(主鍵,值)進新的鍵值對。

  • 值可以修改,使用setValue()直接使用put(舊主鍵,新值)進行覆蓋

  • 在使用迭代器或foreach進行遍歷時注意CME異常,要使用迭代器的remove方法,增加新元素時需要使用新集合接收,在迴圈外將新集合加入舊集合。

2 HashMap集合的特性

  • Map介面的實現類,方法與Map的通用方法相同,但底層需遵循之前學過的hashCode()、==、equals()的比較機制。
  • HashMap的特性與HashSet的其他特性也類似,比如在對集合中元素修改時,不能對已傳入的元素的與雜湊特徵值生成有關的屬性進行直接修改。
import java.util.*;
public class Test{
	public static void main(String[] args){

		HashMap<Student,Integer> map = new HashMap<>();

		Student s1 = new Student("張三", 18);
		Student s2 = new Student("李四", 22);
		Student s3 = new Student("王五", 26);
		Student s4 = new Student("zz", 25);

		map.put(s1,77);
		map.put(s2,88);
		System.out.println(map.containsKey(s4));//--->true
		//因Student物件的hashCode()和equals()都一樣
		//張三、李四被視為相等物件,新加入的李四物件不會加入集合,但年齡所對應的Integer類hashCode()值有不同,故可以加入集合
		//同理可以考慮主鍵名不變,修改value值可以put(舊主鍵名, 新值)直接覆蓋
		//傳入的主鍵相同,但主鍵是唯一的,所以不再新增新的,但value值不同,故可以新增
		System.out.println(map);//--->{張三=88} 
		map.remove(s3);
		System.out.println(map);//--->{}
	}
}

class Student{
	String name;
	int age;

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

	@Override
	public String toString(){
		return name;
	}

	@Override
	public boolean equals(Object obj){
		return true;//任何兩個物件都視為相等物件
	}

	@Override
	public int hashCode(){
		return 1;//任何物件的雜湊碼值都是1
	}
}

  • HashMap和Hashtable之間的區別(Hasntable為最早的Map集合形式)

    • 同步特性
      Hashtable同一時時間允許一個執行緒進行訪問,效率較低,但是不會出現併發錯誤
      HashMap同一時間允許多個執行緒進行訪問,效率較高,但是可能會出現併發錯誤

      JDK5.0開始集合的工具類(Collections)裡面提供一個方法(synchroniedMap()) 可以將執行緒不安全的HashMap變成執行緒安全的集合物件,所以Hashtable被淘汰。但添加了synchronizedMap()之後的HashMap與HashTable無異,都是在分組前上鎖來控制傳入的資料,這時只能逐個進入分組;
      JDK5.0後不如使用util包下concurrent子包中的ConcurrentHashMap集合,對每個小組加鎖,允許進入多個數據,效率更高。

    • 對null容忍度不同
      HashMap無論是主鍵還是值物件,都可以存放null。由於主鍵是唯一,所以主鍵只能存放一個null,Hashtable無論是主鍵還是值物件,都不能存放null,否則都會空指標異常。

    • 底層分組不同
      HashMap預設分16個小組,程式設計師可以按照自己的意願隨意的進行指定分組組數,但是最終一定是2的n次方數,比如定義為17組,最後系統會自動開闢32組。
      Hashtable預設分11個小組,程式設計師可以按照自己的意願隨意指定分組組數。

    • 出現的版本不同
      Hashtable適用於JDK1.0及以後,
      HashMap適用於JDK1.2及以後。

3 TreeMap集合的特性

  • SortedMap介面的實現類,方法與Map的通用方法相同,但底層需遵循之前學過的compareTo()/compare的比較機制。
  • TreeMap的特性與TreeSet的其他特性也類似,比如在對集合中元素修改時,不能對已傳入的元素的與compareTo()/compare有關的屬性進行直接修改。
import java.util.*;
public class Test{
	public static void main(String[] args){

		TreeMap<Student,Integer> map = new TreeMap<>();

		Student s1 = new Student("張三",18);

		map.put(s1,77);

		//compareTo()一直向右比較,因返回值無法返回0而不會停止比較,所以remove()方法無法匹配並返回值
		map.remove(s1);
		System.out.println(map);//--->{張三=77}

		//compareTo()一直向右比較,因返回值無法返回0而不會停止比較,所以containsKey()方法無法匹配並返回值
		System.out.println(map.containsKey(s1));//--->false

		//compareTo()一直向右比較,因返回值無法返回0而不會停止比較,所以get()方法無法匹配並返回值
		System.out.println(map.get(s1));//--->null

		System.out.println(map.size());//--->1
		map.put(s1,77);
		
		//因compareTo()返回值為1可以無限向右子樹新增相同的元素
		System.out.println(map.size());//--->2

	}
}

class Student implements Comparable<Student>{
	String name;
	int age;

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

	@Override
	public String toString(){
		return name;
	}

	@Override
	public int compareTo(Student stu){
		return 1;
	}
}