簡體   English   中英

自定義HashMap代碼問題的實現

[英]Implementation of Custom HashMap code issues

我正在用Java編寫自己的自定義HashMap實現。 以下是我的意見。

public class Entry<K,V> {

private final K key;
private V value; 
private Entry<K,V> next; 

public Entry(K key, V value, Entry<K,V> next) {
    this.key = key;
    this.value = value; 
    this.next = next;
}

public V getValue() {
    return value;
}

public void setValue(V value) {
    this.value = value;
}

public Entry<K, V> getNext() {
    return next;
}

public void setNext(Entry<K, V> next) {
    this.next = next;
}

public K getKey() {
    return key;
}
}



public class MyCustomHashMap<K,V> {

    private int DEFAULT_BUCKET_COUNT = 10;

    private Entry<K,V>[] buckets; 

    public MyCustomHashMap() { 
        buckets = new Entry[DEFAULT_BUCKET_COUNT];
        for (int i = 0;i<DEFAULT_BUCKET_COUNT;i++)
            buckets[i] = null;      
    }

    public void put(K key,V value){

        /**
         * This is the new node. 
         */
        Entry<K,V> newEntry = new Entry<K,V>(key, value, null);

        /**
         * If key is null, then null keys always map to hash 0, thus index 0
         */
        if(key == null){
            buckets[0] = newEntry;
        }

        /** 
         * get the hashCode of the key.
         */
        int hash = hash(key);

        /**
         * if the index does of the bucket does not contain any element then assign the node to the index.  
         */
        if(buckets[hash] == null) {
            buckets[hash] = newEntry;
        } else { 

            /**
             * we need to traverse the list and compare the key with each of the keys till the keys match OR if the keys does not match then we need 
             * to add the node at the end of the linked list. 
             */

            Entry<K,V> previous = null;
            Entry<K,V> current = buckets[hash];

            while(current != null) {

                boolean done = false;

                while(!done) {

                    if(current.getKey().equals(key)) {
                        current.setValue(value); 
                        done = true; // if the keys are same then replace the old value with the new value;   
                    } else if (current.getNext() == null) {
                        current.setNext(newEntry);
                        done = true; 
                    }                   
                    current = current.getNext();
                    previous = current; 
                }
            } 
            previous.setNext(newEntry);
        }


    }

    public V getKey(K key) {

        int hash = hash(key);

        if(buckets[hash] == null) {
            return null;
        } else {
            Entry<K,V> temp = buckets[hash];
            while(temp != null) {
                if(temp.getKey().equals(key))
                    return temp.getValue();  // returns value corresponding to key. 
                temp = temp.getNext();
            }
            return null;  //return null if key is not found. 
        }

    }


    public void display() {

        for(int i = 0; i < DEFAULT_BUCKET_COUNT; i++) {

            if(buckets[i] != null) {
                Entry<K,V> entry = buckets[i];

                while(entry != null){
                    System.out.print("{"+entry.getKey()+"="+entry.getValue()+"}" +" ");
                    entry=entry.getNext();
                }
            }
        }
    }

    public int bucketIndexForKey(K key) {
        int bucketIndex = key.hashCode() % buckets.length;
        return bucketIndex; 
    }


     /**
      * 
      * @param key
      * @return
      */
     private int hash(K key){
         return Math.abs(key.hashCode()) % buckets.length;
     }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyCustomHashMap<String, Integer> myCustomHashMap = new MyCustomHashMap<String, Integer>();
        myCustomHashMap.put("S", 22);
        myCustomHashMap.put("S", 1979);
        myCustomHashMap.put("V", 5);
        myCustomHashMap.put("R", 31);


        System.out.println("Value corresponding to key R: "+myCustomHashMap.getKey("R"));

        System.out.println("Value corresponding to key V: "+myCustomHashMap.getKey("V"));

        System.out.println("Displaying the contents of the HashMap:: ");

        myCustomHashMap.display();

    }

}

1)我覺得put(K鍵,V值)有點瑕疵。 請做好驗證,讓我知道這里有什么問題。 在輸入相同的密鑰時,它給我錯誤的結果。 我還沒有測試它有不同鍵的碰撞情況。

2)據說我們重新哈希hashCode,以便消除hashCode的錯誤實現。 我該怎么做,因為如果我給key的hashCode,即hash(key.hashCode()),那么它不能,因為它無法計算int的hashCode。 這該怎么做?

任何幫助將受到高度贊賞。

謝謝Sid

  1. 您錯誤地處理空鍵:

     if(key == null){ buckets[0] = newEntry; } 

buckets[0]可能已包含條目,在這種情況下,您將丟失這些條目。

  1. 以下循環有一些問題:

      Entry<K,V> previous = null; Entry<K,V> current = buckets[hash]; while(current != null) { boolean done = false; while(!done) { if(current.getKey().equals(key)) { current.setValue(value); done = true; } else if (current.getNext() == null) { current.setNext(newEntry); done = true; } current = current.getNext(); previous = current; // you are not really setting previous to // to the previous Entry in the list - you // are setting it to the current Entry } } previous.setNext(newEntry); // you don't need this statement. You // already have a statement inside the // loop that adds the new Entry to the list 

看起來刪除任何與previous相關的語句將修復此循環。

編輯:

正如kolakao評論的那樣,為了使您的實現變得高效(即需要預期的getput時間),您必須在條目數超過某個閾值時調整HashMap大小(為了使每個桶中的平均條目數為被一個常數約束)。

據說我們重新散列hashCode,以便消除hashCode的錯誤實現。 我該怎么做,因為如果我給key的hashCode,即hash(key.hashCode()),那么它不能,因為它無法計算int的hashCode。 這該怎么做?

重新散列的想法不涉及為密鑰的hashCode調用hashCode 它涉及對key.hashCode()獲取的值運行一些硬編碼函數。

例如,在HashMap Java 7實現中,使用以下函數:

static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

然后你用它:

int hash = hash(key.hashCode());
int bucket = hash % buckets.length;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM