用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 using Object 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
posted @   王铁柱6  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示