手動HashMap的簡單實現
阿新 • • 發佈:2018-12-23
說起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底層的原始碼!