您的位置:首页 > Web前端 > JavaScript

JS中自己实现一个HashMap

2016-03-24 21:20 579 查看
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的认识
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: