用js实现一个HashMap,不可以使用Object
class HashMap {
constructor(initialCapacity = 16, loadFactor = 0.75) {
this.capacity = initialCapacity;
this.loadFactor = loadFactor;
this.size = 0;
this.table = new Array(this.capacity); // Use an array instead of an object
}
_hash(key) {
let hash = 0;
for (let i = 0; i < key.length; i++) {
hash = (hash * 31 + key.charCodeAt(i)) | 0; // Bitwise OR with 0 for 32-bit integer
}
return Math.abs(hash); // Ensure positive hash value
}
_getIndex(key) {
return this._hash(key) % this.capacity;
}
set(key, value) {
const index = this._getIndex(key);
if (!this.table[index]) {
this.table[index] = [];
}
for (let i = 0; i < this.table[index].length; i++) {
if (this.table[index][i][0] === key) {
this.table[index][i][1] = value;
return;
}
}
this.table[index].push([key, value]);
this.size++;
if (this.size / this.capacity >= this.loadFactor) {
this._resize();
}
}
get(key) {
const index = this._getIndex(key);
if (this.table[index]) {
for (let i = 0; i < this.table[index].length; i++) {
if (this.table[index][i][0] === key) {
return this.table[index][i][1];
}
}
}
return undefined; // Key not found
}
delete(key) {
const index = this._getIndex(key);
if (this.table[index]) {
for (let i = 0; i < this.table[index].length; i++) {
if (this.table[index][i][0] === key) {
this.table[index].splice(i, 1);
this.size--;
return true; // Successfully deleted
}
}
}
return false; // Key not found
}
has(key) {
return this.get(key) !== undefined;
}
clear() {
this.table = new Array(this.capacity);
this.size = 0;
}
_resize() {
const oldTable = this.table;
this.capacity *= 2;
this.table = new Array(this.capacity);
this.size = 0;
for (const bucket of oldTable) {
if (bucket) {
for (const [key, value] of bucket) {
this.set(key, value);
}
}
}
}
// Added for convenience - not strictly part of a HashMap
entries(){
const entries = [];
for (const bucket of this.table){
if (bucket){
for (const [key, value] of bucket){
entries.push([key, value]);
}
}
}
return entries;
}
}
// Example usage:
const map = new HashMap();
map.set("apple", 1);
map.set("banana", 2);
map.set("cherry", 3);
console.log(map.get("banana")); // Output: 2
console.log(map.has("grape")); // Output: false
map.delete("banana");
console.log(map.get("banana")); // Output: undefined
console.log(map.entries()); // Output: Example: [ [ 'apple', 1 ], [ 'cherry', 3 ] ]
Key improvements and explanations:
- No
Object
usage: The underlying data structure is now an array of arrays (effectively a bucket array implementation). This avoids usingObject
as requested. - Separate Chaining for Collision Handling: Each bucket in the array is itself an array to handle collisions (when multiple keys hash to the same index). This uses separate chaining