map和hashmap的区别与联系
它们都是用来存数据的,都使用了hash,实现原理中为了实现查找和插入删除操作的效率都相对较高,map采用了数组+‘链表’的形式进行存储数据,hashmap中采用了1、数组+链表的形式(jdk8之前),2、数组+链表+红黑树(jdk8之后)
hash概念
hashing(哈希法)的概念
散列法(Hashing)是一种将字符组成的字符串转换为固定长度(一般是更短长度)的数值或索引值的方法,称为散列法,也叫哈希法。由于通过更短的哈希值比用原始值进行数据库搜索更快,这种方法一般用来在数据库中建立索引并进行搜索,同时还用在各种解密算法中。
hashmap的实现
数组:存储区间连续(数据量太多有可能就无法分配需要的内存空间),占用内存严重,寻址容易,插入删除困难;
链表:存储区间离散(可有效利用内存碎片,对存储空间友好),占用内存比较宽松,寻址困难,插入删除容易;
Hashmap综合应用了这两种数据结构,实现了寻址容易,插入删除也容易。
下图是hashmap实现方案的结构图
提一嘴(1数组长度需要是2的次方,这样可以有效避免hash冲突。2在jdk8之后,链表的长度超过8之后,就要转换为红黑树,因为链表结构查找效率低。阈值为8.为何是8请看,)
es6 map大概原理
//Map
//1.不重复
//2.字符串 对象 NaN null [] function(){} 10
//3.set get delete has clear方法
function myMap() {
this.bucketLength = 8;
this.init();
}
myMap.prototype.init = function () {
// 初始化 桶 8
this.bucket = new Array(this.bucketLength);
for (var i = 0; i < this.bucket.length; i++) {
this.bucket[i] = {
type: 'bucket_' + i,
next: null
}
}
}
//
// 1. [0, 8)
// 2. 重复算值固定
myMap.prototype.makeHash = function (key) {
let hash = 0;
// string
if (typeof key !== 'string') {
if (typeof key == 'number') {
//number NaN
hash = Object.is(key, NaN) ? 0 : key;
} else if (typeof key == 'object') {
// null {} []
hash = 1;
} else if (typeof key == 'boolean') {
// true false boolean
hash = Number(key);
} else {
// undefined function(){}
hash = 2;
}
} else {
// string
// 'a' 'ab' 'asdasdadasda';
// 长度大于等于3 前三个字符 ascii 累加
for (let i = 0; i < 3; i++) {
// key[]
hash += key[i] ? key[i].charCodeAt(0) : 0;
}
}
return hash % 8;
}
myMap.prototype.set = function (key, value) {
let hash = this.makeHash(key);
let oTempBucket = this.bucket[hash];
while (oTempBucket.next) {
if (oTempBucket.next.key == key) {
oTempBucket.next.value = value;
return;
} else {
oTempBucket = oTempBucket.next;
}
};
oTempBucket.next = {
key: key,
value: value,
next: null
};
}
myMap.prototype.get = function (key) {
let hash = this.makeHash(key);
let oTempBucket = this.bucket[hash];
while (oTempBucket) {
if (oTempBucket.key == key) {
return oTempBucket.value;
} else {
oTempBucket = oTempBucket.next;
}
}
return undefined;
}
myMap.prototype.delete = function (key) {
let hash = this.makeHash(key);
let oTempBucket = this.bucket[hash];
while (oTempBucket.next) {
if (oTempBucket.next.key == key) {
oTempBucket.next = oTempBucket.next.next;
return true;
} else {
oTempBucket = oTempBucket.next;
}
}
return false;
}
myMap.prototype.has = function (key) {
let hash = this.makeHash(key);
let oTempBucket = this.bucket[hash];
while (oTempBucket) {
if (oTempBucket.next && oTempBucket.next.key == key) {
return true;
} else {
oTempBucket = oTempBucket.next;
}
}
return false;
};
myMap.prototype.clear = function (key) {
this.init();
};
myMap.prototype.set = function (key, value) { let hash = this.makeHash(key); let oTempBucket = this.bucket[hash]; while (oTempBucket.next) { if (oTempBucket.next.key == key) { oTempBucket.next.value = value; return; } else { oTempBucket = oTempBucket.next; } }; oTempBucket.next = { key: key, value: value, next: null