JS中本身實現一個HashMap

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

相關文章
相關標籤/搜索