Java哈希表实现

时间:2013-06-04 22:32:41

标签: java hash hashtable

在我的哈希表实现中,我的哈希函数只是获取我传递的项的值,调用hashCode(继承自Object类),并以内部数组的大小为模。此内部数组是LinkedLists数组。现在,如果我的LinkedLists变得太长(并且我的效率开始从O(1)滑落到O(n)),我认为简单地增加数组的大小是有意义的。但这就是我的问题所在,因为我说我散列了我传递的项目并模数数组的大小(刚刚更改)。如果我要继续,哈希是否会指向数组中的不同索引,从而失去引用哈希表中的项目的能力?我怎么能解决这个问题?

2 个答案:

答案 0 :(得分:1)

您需要每个项目的实际哈希值,以便您可以将它们放入已调整大小的表中的正确哈希链中。 (否则,正如您所观察到的那样,这些物品可能最终会出现在错误的链条上,并且因此无法定位。)

有两种方法可以解决这个问题:

  • 您可以在将每个项目添加到新表格时重新计算每个项目的哈希值。

  • 您可以保留哈希链中每个项目的原始哈希值的副本。这就是标准的Java HashMap实现所做的...至少在我看过的版本中。

(后者是时间与空间的权衡,如果你的物品有昂贵的hashcode方法,那么可以支付大笔时间。但是,如果你在一生中分期付款,那么哈希表,这种优化不会改变任何公共API方法的“大O”复杂性...假设你的哈希表大小调整是指数级的;例如你每次大约两倍的表大小。)

答案 1 :(得分:0)

package com.codewithsouma.hashtable;

import java.util.LinkedList;

public class HashTable {

    private class Entry {
        private int key;
        private String value;

        public Entry(int key, String value) {
            this.key = key;
            this.value = value;
        }
    }

    LinkedList<Entry>[] entries = new LinkedList[5];

    public void put(int key, String value) {
        var entry = getEntry(key);
        if (entry != null){
            entry.value = value;
            return;
        }

        getOrCreateBucket(key).add(new Entry(key,value));
    }

    public String get(int key) {
        var entry = getEntry(key);
        return  (entry == null) ? null : entry.value;
    }

    public void remove(int key) {
       var entry = getEntry(key);
       if (entry == null)
           throw new IllegalStateException();

      getBucket(key).remove(entry);
    }

    private LinkedList<Entry> getBucket(int key){
        return entries[hash(key)];
    }

    private LinkedList<Entry> getOrCreateBucket(int key){
        var index = hash(key);
        var bucket = entries[index];
        if (bucket == null) {
            entries[index] = new LinkedList<>();
            bucket = entries[index];
        }
        return bucket;
    }

    private Entry getEntry(int key) {
        var bucket = getBucket(key);
        if (bucket != null) {
            for (var entry : bucket) {
                if (entry.key == key) return entry;
            }
        }
        return null;
    }

    private int hash(int key) {
        return key % entries.length;
    }

}