1. 程式人生 > >深入理解集合框架層次結構(篇二)

深入理解集合框架層次結構(篇二)

本篇我們來談對映(Map)

Map

對映資料結構是用來儲存具有對映關係的資料,當要檢視一個元素時,需要查詢元素的精確副本。因此Map集合裡存放著兩組值key(鍵)和value(值)。其中key值唯一,不能重複,value值可重複。Java類庫為對映提供了兩個通用實現:HashMap(雜湊對映)和TreeMap(樹對映),這兩個類都實現了Map介面。

Map是無序的,(這裡的有序和無序不是指集合中的排序,而是是否按照元素新增的順序來儲存物件。)它的儲存結構是雜湊表<key,value>鍵值對,map中插入元素是根據key計算出的雜湊值來儲存元素的,因此他不是按照元素的新增順序來儲存物件的,所以Map是無序的。它的實現類有:HashMap、TableMap和TreeMap。(LinkedHashMap是有序的)

應該選擇雜湊對映還是樹對映呢?

HashMap(雜湊對映):

HashMap 的例項有兩個引數影響其效能:“初始容量” 和 “載入因子”。容量 是雜湊表中桶的數量,初始容量 只是雜湊表在建立時的容量。載入因子 是雜湊表在其容量自動增加之前可以達到多滿的一種尺度。當雜湊表中的條目數超出了載入因子與當前容量的乘積時,則要對該雜湊表進行 rehash 操作(即重建內部資料結構),從而雜湊表將具有大約兩倍的桶數。

  • HashMap基於雜湊散列表實現,隨機儲存,無序。
  • 無論對於主鍵還是值都允許存為"null",只不過對於主鍵而言要求唯一性,所以key中最多存一個"null".
  • HashMap 執行緒不安全,同一時間允許多個執行緒同時進行操作,效率相對較高,但是可能會出現併發錯誤.

HashMap對外提供的常見訪問介面:

  • put ()  ----HashMap物件可通過put()將對映關係資料(key--value)新增到HashMap中。
  • isEmpty()  ----判斷是否為空
  • get()  ----獲取key對應的value值
  • containsKey  ----判斷HashMap是否包含key
  • containsvalue  ----判斷HashMap是否包含value元素
  • putAll()  ----將具有多個對映關係資料的全部元素新增到HashMap中
  • remove()  ----刪除鍵值為key的value值
  • clear()  ----清空HashMap,它是通過將所有的元素設為null來實現的。
  • enrtrySet()  ----返回“HashMap中所有Entry的集合”,它是一個集合。
  • keySet()  ----返回一個Set介面

HashMap遍歷方式:

  • 遍歷HashMap“鍵”集合:

keySet()  ----根據keySet()獲取HashMap的“鍵”的Set集合,要想得到“value”,必須先得到key,再通過get(key)得到value(value依賴key)。

  • 遍歷HashMap“值”集合:

values()  ----根據values()獲取HashMap的“值”集合,再通過Iterator迭代器Next()得到值。

  • 遍歷HashMap“鍵值對”集合:

entrySet()  ----根據entrySet()獲取HashMap的“鍵值對”的Set集合,可通過get(key)和get(value)分別可直接得到兩者的值(key和value不依賴)。

例:

package net.csdn.qf.homework;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
/**
 * @author 北冥有熊
 *  2018年11月5日
 */
public class Test01 {
	public static void main(String[] args) {
		HashMap<String, String> hm = new HashMap<String,String>();
		hm.put("00001", "張三");
		hm.put("00002", "李四");
		hm.put("00018", "王麻子");
		hm.put("00009", "趙武");
		System.out.println("=============="+hm); //無序輸出
		
		//KeySet遍歷
		Set<String> keySet = hm.keySet();//根據keySet()獲取HashMap的“鍵”的Set集合。
		//通過Iterator迭代器開始遍歷“第一步”得到的集合。
		Iterator<String> iterator = keySet.iterator();
		System.out.println("通過keySet遍歷:");//
		while(iterator.hasNext()) {
			String key = iterator.next(); //得到鍵
			String value = hm.get(key); //通過鍵得到值
			System.out.println(key+":"+value);
		}
		
		//entrySet遍歷
		Set<Entry<String, String>> entrySet = hm.entrySet();//根據entrySet()
								//獲取HashMap的“鍵值對”的Set集合
		//通過Iterator迭代器開始遍歷“第一步”得到的集合。
		Iterator<Entry<String, String>> iterator2 = entrySet.iterator();
		System.out.println("通過entrySet遍歷:");
		while(iterator2.hasNext()) {
			Entry<String, String> entry = iterator2.next();//得到下一個
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key+":"+value);
			
		}
		//values遍歷值
		Collection<String> c = hm.values();
		Iterator<String> iterator3 = c.iterator();
		System.out.println("通過values遍歷:");
		while (iterator3.hasNext()) {
			String value = iterator3.next();
			System.out.println(value);
		}
	}
}

TreeMap(樹對映):

TreeMap是一個鍵值唯一且有序的集合,底層實現基於“紅黑樹”。(紅黑樹:根節點是黑色,黑色的子節點必然是紅色,從根節點到葉子節點含有的黑色數量是一致的。有關紅黑樹的實現原理參考https://www.cnblogs.com/CarpenterLee/p/5503882.html)。

HashMap 執行緒不安全,同一時間允許多個執行緒同時進行操作,效率相對較高,但是可能會出現併發錯誤.

由於TreeMap是有序的,故有特有方法時hashMap沒有的。比如:

  • firstEntry()  ----返回一個與該圖的最小金鑰相關的鍵值對映,或 null如果Map是空的。
  • firstKey()  ----返回當前在該Map中的第一個(最低)鍵。

更多方法參見API

TreeMap遍歷方式:

  • 遍歷HashMap“鍵”集合:

keySet()  ----根據keySet()獲取HashMap的“鍵”的Set集合,要想得到“value”,必須先得到key,再通過get(key)得到value(value依賴key)。

  • 遍歷HashMap“值”集合:

values()  ----根據values()獲取HashMap的“值”集合,再通過Iterator迭代器Next()得到值。

  • 遍歷HashMap“鍵值對”集合:

entrySet()  ----根據entrySet()獲取HashMap的“鍵值對”的Set集合,可通過get(key)和get(value)分別可直接得到兩者的值(key和value不依賴)。

例:

package net.csdn.qf.test;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class Test06 {
	public static void main(String[] args) {
		TreeMap<String, Integer> aMap = new TreeMap<String,Integer>();
		aMap.put("AA", 18);
		aMap.put("BB", 9);
		aMap.put("CC", 100);
		System.out.println(aMap);
		
		//keySet遍歷
		Set<String> keySet = aMap.keySet();
		Iterator<String> iterator = keySet.iterator();
		System.out.println("keySet遍歷");
		while (iterator.hasNext()) {
			String key = iterator.next();
			Integer value = aMap.get(key);
			System.out.println(key+":"+value);
		}
		//entrySet遍歷
		Set<Entry<String, Integer>> entrySet = aMap.entrySet();
		Iterator<Entry<String, Integer>> iterator2 = entrySet.iterator();
		System.out.println("entrySet遍歷");
		while (iterator2.hasNext()) {
			Entry<String, Integer> nextEntry = iterator2.next();
			String key = nextEntry.getKey();
			Integer value = nextEntry.getValue();
			System.out.println(key+":"+value);
		}
		//value遍歷
		Collection<Integer> values = aMap.values();
		Iterator<Integer> iterator3 = values.iterator();
		System.out.println("value遍歷");
		while (iterator3.hasNext()) {
			Integer value = iterator3.next();
			System.out.println(value);
		}
	}
}

更多底層原理持續更新中。。。