自定义HashMap代码问题的实现

时间:2016-05-13 07:47:32

标签: java hashmap

我正在用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 个答案:

答案 0 :(得分:3)

  1. 您错误地处理空键:

    if(key == null){
        buckets[0] = newEntry;
    }
    
  2. 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
      
    2. 看起来删除与previous相关的任何语句都会修复此循环。

      编辑:

      正如kolakao评论的那样,为了使您的实施更有效(即getput需要预期的固定时间),您必须在条目数超过时调整HashMap的大小一些阈值(为了使每个桶中的平均条目数由常量绑定)。

        

      据说我们重新散列hashCode,以便消除hashCode的错误实现。我该怎么做,因为如果我给key的hashCode,即hash(key.hashCode()),那么它不能,因为它无法计算int的hashCode。怎么做?

      重新散列的想法不涉及为密钥的hashCode调用hashCode。它涉及对key.hashCode()获得的值运行一些硬编码函数。

      例如,在Java 7的{​​{1}}实现中,使用了以下函数:

      HashMap

      然后你用它:

      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);
      }