Java中HashMap是一個很是實用的集合類,其方便的存取操做爲咱們提供了極大的便利javascript
JS中並無爲咱們提供Map集合,借鑑Java中HashMap的思路,本身實現了一個HashMap,還不是很是完善,主要提供了put與get操做,後續將會繼續完善html
HashMap.jsjava
//實現HashMap /** * 自定義HashMap */ function HashMap() { // 最大容量(必須是2的冪且小於2的30次方,傳入容量過大將被這個值替換) var maxCapacity = 1 << 30; // HashMap的默認容量大小(2^n) var initialCapacity = 16; // HashMap的實際大小,默認爲initialCapacity var capacity = initialCapacity; // 默認的負載因子 var loadFactor = 0.75; // 臨界值 var threshold = capacity * loadFactor; // 已用空間 var size = 0; // map結構被改變的次數 var modCount = 0; // 存放鍵值對key-value var table = new Array(capacity); /** * 冪次方化capacity */ function powerCapacity() { while (capacity < initialCapacity) { capacity <<= 1; } } /** * 私有方法 hashCode方法 * str: 待計算的字符串 */ function hashCode(str) { var hash = 0; var tempStr = JSON.stringify(str); if (tempStr.length === 0) { return hash; } for (var i = 0, len = tempStr.length; i < len; i++) { chr = tempStr.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; } return hash; } /** * equals方法 */ function equals(objf, objs) { if (objf == null || objs == null) { return false; } if (objf == objs) { return true; } return false; } /** * 將key-value對添加到table索引位置爲bucketIndex中 */ function addEntry(h, k, v, bucketIndex) { // 獲取指定 bucketIndex 索引處的 Entry var entry = table[bucketIndex]; // 將新建立的 Entry放入 bucketIndex索引處,並讓新的 Entry指向原來的 Entry table[bucketIndex] = { hash : h, key : k, value : v, next : entry }; // size超過臨界值,默認擴充至當前table長度的兩倍 if (size++ >= threshold) { resize(2 * table.length); } } /** * 擴容 */ function resize(newCapacity) { var oldTable = table; var oldCapacity = oldTable.length; if (oldCapacity == maxCapacity) { threshold == Number.MAX_VALUE; return; } // 建立新數組,容量爲指定的容量 var newTable = new Array(newCapacity); transfer(newTable); // 設置下一次須要調整數組大小的界限 threshold = newCapacity * loadFactor; } function transfer(newTable) { // 保留原數組的引用到src中 var src = table; var newCapacity = newTable.length; for (var j = 0; j < src.length; j++) { var e = src[j]; if (e != null) { // 將原數組中的元素置爲null src[j] = null; // 遍歷原數組中j位置指向的鏈表 do { var next = e.next; // 根據新的容量計算e在新數組中的位置 var i = indexFor(e.hash, newCapacity); // 將e插入到newTable[i]指向的鏈表的頭部 e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } } /** * 私有方法 hash方法 * h: hashCode(key)的值 */ function hash(h) { // 無符號右移,高位補0 h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } /** * 私有方法 indexFor方法 * h: hashCode(key)的值 * length: table的長度 */ function indexFor(h, length) { return h & (length - 1); } /** * 當調用put(k,v)方法存入鍵值對時,若是k已經存在,則該方法被調用 */ function recordAccess(entry) { } /** * 當Entry被從HashMap中移除時被調用 */ function recordRemoval(entry) { } /** * 公有方法 存儲鍵值對 * key: value: */ if (HashMap.prototype.put == undefined) { HashMap.prototype.put = function(key, value) { // 不容許key爲空 if (key == null) { throw "the key can not be null,but the key of entry" + " map[" + size + "] is null"; return; } // 根據key的hashCode再次計算hash值 var hashVal = hash(hashCode(key)); // 根據hash值計算在table中的索引 var index = indexFor(hashVal, table.length); // 若是table[index] != null,說明該位置上已經有元素 for (var e = table[index]; e != null; e = e.next) { var k; if (e.hash == hashVal && ((k = e.key) == key || equals(key, k))) { var oldValue = e.value; e.value = value; recordAccess(e); return oldValue; } } modCount++; addEntry(hashVal, key, value, index); return null; }; } /** * 公有方法 根據給定的key獲取value * key: 關鍵字 */ if (HashMap.prototype.get == undefined) { HashMap.prototype.get = function(key) { if (key == null) { return null; } var hashVal = hash(hashCode(key)); for (var e = table[indexFor(hashVal, table.length)]; e != null; e = e.next) { var k; if (e.hash == hashVal && ((k = e.key) == key || equals(key, k))) { return e.value; } } return null; }; } /** * 返回HashMap的大小 */ if (HashMap.prototype.size == undefined) { HashMap.prototype.size = function() { return size; }; } /** * 清除HashMap中的內容 */ if (HashMap.prototype.clear == undefined) { HashMap.prototype.clear = function() { modCount++; var tab = table; for (var i = 0; i < tab.length; i++) { tab[i] = null; } size = 0; }; } }
test.html數組
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My HashMap</title> <script type="text/javascript" src="HashMap.js"></script> </head> <body> <script type="text/javascript"> var map = new HashMap(); map.put("name", "marry"); map.put(123, 123); console.log(map.get("name")); console.log(map.get(123)); </script> </body> </html>
經過本次本身動手實現一個簡單的HashMap,增長了本身對Java中HashMap的認識prototype