HashMap实现如何在java中更快更好

时间:2017-04-17 12:09:56

标签: java hashmap

我有HashMap实现,但操作对我来说太慢了它必须更快,就像普通的hashmap一样。 这是代码:

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

}

当我尝试输入大数据时,例如:

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

这需要太长时间。我必须在没有其他集合的情况下实现它:Set等我必须更快地放置,删除,获取和包含Key,就像普通的hashMap一样,但我不知道如何实现快速映射。

1 个答案:

答案 0 :(得分:1)

你的地图很慢的原因是因为你有很多碰撞。你的容量是4,你永远不会扩展它。因此,put()操作在4次put()次调用后有效地变为大约O(N)。同样如William所述,您可以在桶的末尾添加新条目。因此,将其更改为添加为第一个元素将提高性能。但是,将地图保持为4的常量并不是一个好习惯 - 因为put()会很好但get()仍然是O(N)

EDIT 您不能在前面添加条目。因为您必须检查存储桶上的所有条目,以确保您没有相等的