2017-04-17 1 views
-2

Ich habe HashMap Implementierung, aber die Operationen sind zu langsam für mich muss es schneller sein, wie normal hashmap. Dies ist der Code:HashMap Implementierung wie es schneller und besser in Java

package Map; 
public class HashMap<K, V> { 

private Entry<K, V>[] table; // Array of Entry. 
private int capacity = 4; // Initial capacity of HashMap 

static class Entry<K, V> { 
    K key; 
    V value; 
    Entry<K, V> next; 

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

@SuppressWarnings("unchecked") 
public HashMap() { 
    table = new Entry[capacity]; 
} 

/** 
* Method allows you put key-value pair in HashMapCustom. If the map already 
* contains a mapping for the key, the old value is replaced. Note: method 
* does not allows you to put null key though it allows null values. 
* Implementation allows you to put custom objects as a key as well. Key 
* Features: implementation provides you with following features:- >provide 
* complete functionality how to override equals method. >provide complete 
* functionality how to override hashCode method. 
* 
* @param newKey 
* @param data 
*/ 
public void put(K newKey, V data) { 
    if (newKey == null) 
     return; // does not allow to store null. 

    // calculate hash of key. 
    int hash = hash(newKey); 
    // create new entry. 
    Entry<K, V> newEntry = new Entry<K, V>(newKey, data, null); 

    // if table location does not contain any entry, store entry there. 
    if (table[hash] == null) { 
     table[hash] = newEntry; 
    } else { 
     Entry<K, V> previous = null; 
     Entry<K, V> current = table[hash]; 

     while (current != null) { // we have reached last entry of bucket. 
      if (current.key.equals(newKey)) { 
       if (previous == null) { // node has to be insert on first of 
             // bucket. 
        newEntry.next = current.next; 
        table[hash] = newEntry; 
        return; 
       } else { 
        newEntry.next = current.next; 
        previous.next = newEntry; 
        return; 
       } 
      } 
      previous = current; 
      current = current.next; 
     } 
     previous.next = newEntry; 
    } 
} 

/** 
* Method returns value corresponding to key. 
* 
* @param key 
*/ 
public V get(K key) { 
    int hash = hash(key); 
    if (table[hash] == null) { 
     return null; 
    } else { 
     Entry<K, V> temp = table[hash]; 
     while (temp != null) { 
      if (temp.key.equals(key)) 
       return temp.value; 
      temp = temp.next; // return value corresponding to key. 
     } 
     return null; // returns null if key is not found. 
    } 
} 

public boolean containsKey(K key) { 
    int hash = hash(key); 
    if (table[hash] == null) { 
     return false; 
    } else { 
     Entry<K, V> temp = table[hash]; 
     while (temp != null) { 
      if (temp.key.equals(key)) 
       return true; 
      temp = temp.next; // return value corresponding to key. 
     } 
    } 
    return false; 
} 

/** 
* Method removes key-value pair from HashMapCustom. 
* 
* @param key 
*/ 
public boolean remove(K deleteKey) { 

    int hash = hash(deleteKey); 

    if (table[hash] == null) { 
     return false; 
    } else { 
     Entry<K, V> previous = null; 
     Entry<K, V> current = table[hash]; 

     while (current != null) { // we have reached last entry node of 
            // bucket. 
      if (current.key.equals(deleteKey)) { 
       if (previous == null) { // delete first entry node. 
        table[hash] = table[hash].next; 
        return true; 
       } else { 
        previous.next = current.next; 
        return true; 
       } 
      } 
      previous = current; 
      current = current.next; 
     } 
     return false; 
    } 

} 

/** 
* Method displays all key-value pairs present in HashMapCustom., insertion 
* order is not guaranteed, for maintaining insertion order refer 
* LinkedHashMapCustom. 
* 
* @param key 
*/ 
public void display() { 

    for (int i = 0; i < capacity; i++) { 
     if (table[i] != null) { 
      Entry<K, V> entry = table[i]; 
      while (entry != null) { 
       System.out.print("{" + entry.key + "=" + entry.value + "}" + " "); 
       entry = entry.next; 
      } 
     } 
    } 

} 

/** 
* Method implements hashing functionality, which helps in finding the 
* appropriate bucket location to store our data. This is very important 
* method, as performance of HashMapCustom is very much dependent on this 
* method's implementation. 
* 
* @param key 
*/ 
private int hash(K key) { 
    return Math.abs(key.hashCode()) % capacity; 
} 

} 

Und wenn ich große Daten setzen versuchen, wie:

HashMap<Integer,String> map = new HashMap(); 
long startTime = System.currentTimeMillis(); 
for(int i = 0 ; i < 200000000; i++){ 
map.put(i, "kotek"+i); 
} 
System.out.println(System.currentTimeMillis() - startTime); 

Es dauert zu lange Zeit. Ich muss es ohne weitere Sammlungen wie: Set usw. implementieren. Ich muss setzen, entfernen, holen und containsKey schneller, wie normale hashMap, aber ich weiß nicht, wie diese schnelle Karte implementieren.

+1

Sie finden die Implementierung [hier] (http://grepcode.com/file/repository.grepcode.com /java/root/jdk/openjdk/6-b14/java/util/HashMap.java). –

+1

Ich denke, eine gute Idee wäre, den "Entry" im Falle einer Hash-Kollision voranzustellen, bevor man ihn am Ende hinzufügt. –

+0

@WillemVanOnsem Sie können den Eintrag nicht voranstellen, da Sie sicherstellen müssen, dass Sie nicht bereits den gleichen Schlüssel haben. Dafür müssen Sie jeden Eintrag im Bucket überprüfen – paranoidAndroid

Antwort

1

Der Grund, warum Ihre Karte langsam ist, ist, weil Sie viele Kollisionen haben. Ihre Kapazität ist 4 und Sie erweitern sie nie. So effektiv der put() Betrieb wird ungefähr O (N) nach den 4 ersten put() Anrufe. Wie bereits erwähnt, fügen Sie Ihre neuen Einträge am Ende des Buckets hinzu. Wenn Sie das als erstes Element hinzufügen, wird die Leistung erhöht. Aber es ist noch keine gute Praxis, um Ihre Karte in konstanter Größe von 4 zu halten - da Ihre put() in Ordnung sein, aber get() wird immer noch O (N)

EDIT Sie den Eintrag nicht voranstellen können. Da müssen Sie über alle Einträge auf dem Bucket gehen, um sicherzustellen, dass Sie nicht bereits eine gleich Schlüssel haben

Verwandte Themen