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