JS中自己实现一个HashMap

Java中HashMap是一个非常实用的集合类,其方便的存取操作为我们提供了极大的便利

JS中并没有为我们提供Map集合,借鉴Java中HashMap的思路,自己实现了一个HashMap,还不是非常完善,主要提供了put与get操作,后续将会继续完善

  • HashMap.js

//实现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的认识

转载于:https://my.oschina.net/migoo/blog/646935

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值