[英]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
您錯誤地處理空鍵:
if(key == null){ buckets[0] = newEntry; }
buckets[0]
可能已包含條目,在這種情況下,您將丟失這些條目。
以下循環有一些問題:
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評論的那樣,為了使您的實現變得高效(即需要預期的get
和put
時間),您必須在條目數超過某個閾值時調整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.