1. 程式人生 > >手動HashMap的簡單實現

手動HashMap的簡單實現

說起HashMap的強大之處,就是其內部使用了雜湊演算法和連結串列演算法,充分利用好載入因子的強大推動,使得在時間和空間上的成本尋求一種折中,其內部元素在儲存和提取不僅可以充分利用好HashMap初始化的空間,而且查詢效率及其的高!

在面試中,面試官會常問HashMap的底層原始碼的實現,接下來我簡單的手動實現一個HashMap集合:

(一)HashMap中儲存的元素型別即為鍵值對存在,定義一個能包含鍵值對的內部類:

class MapEntry {
	Object key;
	Object value;

	public MapEntry(Object key, Object value) {
		super();
		this.key = key;
		this.value = value;
	}
}

(二)我們使用java.util.LinkedList雙向連結串列來模擬HashMap中底層實現的陣列(即連結串列陣列)

/**
 * 1.提高查詢的效率 2.預設載入因子 (0.75) 即在時間和空間成本上尋求一種折衷。載入因子過大儲存空間能得到充分利用,但查詢效率會低一點;
 * 載入因子過小,儲存空間利用率降低,但是查詢速度會高一點!(載入因子的設計大小要保證儲存空間充分利用,且查詢效率高)
 */
public class ManualHashMap {

	LinkedList[] arr = new LinkedList[999]; // 鍵值對集合! Map底層結構是:陣列 + 連結串列
	int size = 0; // HashMap的容量

	// 構造方法
	public ManualHashMap() {
	}

	/*
	 * 向HashMap中存入鍵值對
	 */
	public void put(Object key, Object value) {
		MapEntry node = new MapEntry(key, value);
		/*
		 * 獲取該鍵值對在陣列中的索引位置(0~998);
		 * 重寫HashCode()方法就是為了讓具有相同屬性物件具有相同的HashCode值(地址碼);
		 * 由於重寫HashCode()方法在任何種程度上,都會出現一定的Bug,使得具有不同屬性值都會有相同的HashCode碼值;
		 * 此時就需要重寫equals()方法,進行二次比較key值是否相同,就可做到萬無一失了!
		 */
		int hash = node.key.hashCode() % arr.length;
		hash = hash < 0 ? -hash : hash;
		if (arr[hash] == null) { // 此索引位置為空
			LinkedList<MapEntry> list = new LinkedList<>();	//建立一個雙向連結串列
			arr[hash] = list;
			list.add(node);
			size++;
		} else { // 該位置有元素
			LinkedList<MapEntry> list = arr[hash]; // 取出該索引處的連結串列
			// 判斷有沒有鍵值重複
			boolean flag = false;//判斷此連結串列中,是否存在重複的鍵值
			for (int i = 0; i < list.size(); i++) {
				MapEntry temp = (MapEntry) list.get(i);
				if (temp.key.equals(key)) { // 鍵值有重複
					temp.value = value; // value值覆蓋
					flag = true;
				}
			}
			if(!flag){	//不存在重複的key,需新增此元素
				list.add(node);
				size++;
			}
		}
	}

	/*
	 * 獲取鍵值對中某個鍵值對物件
	 */
	public Object get(Object key) {
		int hash = key.hashCode() % arr.length;
		hash = hash < 0 ? -hash : hash;
		if (arr[hash] != null) {
			LinkedList<MapEntry> list = arr[hash];
			for (int i = 0; i < list.size(); i++) {
				MapEntry temp = (MapEntry) list.get(i);
				if(temp.key.equals(key)){
					return temp.value;
				}
			}
		}
		return null;
	}

	public static void main(String[] args) {
		ManualHashMap map = new ManualHashMap();
		map.put("6", "b");
		map.put("6", "a");
		map.put("5", "c");
		map.put("4", "d");
		System.out.println(map.size);	//3
		System.out.println(map.get("6"));	//a
	}
}
本人只是簡單的實現了HashMap存取資料的詳細過程,載入因子以及陣列的擴容再次賦值,過於繁瑣,若需理解深透,請自行查閱HashMap底層的原始碼!