HashTable实现

来源:互联网 发布:转盘抽奖软件注册码 编辑:程序博客网 时间:2024/05/07 08:50
1.
散列函数的实现算法:Doug Lea's supplemental secondaryHash function (inlined).
碰撞解决:采用拉链法,实现的过程基本同<算法>
拉链法:数组+链表(每个数组的item是链表)实现

2.构造函数
public HashMap() {
        table = (HashMapEntry<K, V>[]) EMPTY_TABLE;
// threshold:resize数组大小的上限值(一般取最大容量的3/4)
        threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
    }

private static final Entry[] EMPTY_TABLE
= new HashMapEntry[MINIMUM_CAPACITY >>> 1];// MINIMUM_CAPACITY==4


3.put函数
    @Override public V put(K key, V value) {
        ...


        int hash = secondaryHash(key); // 散列函数Doug Lea's supplemental
        HashMapEntry<K, V>[] tab = table; // table保存键值对的map集合
        int index = hash & (tab.length - 1); // table的大小都是2^n,每次容量扩大都是两倍扩大
        for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
            if (e.hash == hash && key.equals(e.key)) { // 之前有put该map(key,value),则修改value的值
preModify(e); // 该函数在LinkedHashMap有覆盖实现,调用makeTail
                V oldValue = e.value;
                e.value = value;
                return oldValue;
            }
        }


/ 之前没有put该map(key,value)
        // No entry for (non-null) key is present; create one
        modCount++;
        if (size++ > threshold) {
            tab = doubleCapacity();
            index = hash & (tab.length - 1);
        }
        addNewEntry(key, value, hash, index);
        return null;
    }
// 容量扩大一倍
private HashMapEntry<K, V>[] doubleCapacity() {
HashMapEntry<K, V>[] oldTable = table;
int oldCapacity = oldTable.length;


int newCapacity = oldCapacity * 2;// 容量扩大策略:扩大两倍
HashMapEntry<K, V>[] newTable = makeTable(newCapacity);


// 重新hash原来旧的table
for (int j = 0; j < oldCapacity; j++) {// 对每个链表进行重新hash
/*
* Rehash the bucket using the minimum number of field writes.
* This is the most subtle and delicate code in the class.
*/
HashMapEntry<K, V> e = oldTable[j];
if (e == null) {
continue;
}

// 重新hash每个item对应的链表的每个元素
int highBit = e.hash & oldCapacity;
HashMapEntry<K, V> broken = null;
newTable[j | highBit] = e;
// 变量链表每个元素
for (HashMapEntry<K, V> n = e.next; n != null; e = n, n = n.next) {
int nextHighBit = n.hash & oldCapacity;
if (nextHighBit != highBit) {
if (broken == null)
newTable[j | nextHighBit] = n;
else
broken.next = n;
broken = e;
highBit = nextHighBit;
}
}
if (broken != null)
broken.next = null;
}
return newTable;
}

// 创建新表格
private HashMapEntry<K, V>[] makeTable(int newCapacity) {
@SuppressWarnings("unchecked") HashMapEntry<K, V>[] newTable
= (HashMapEntry<K, V>[]) new HashMapEntry[newCapacity];
table = newTable;
threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity
return newTable;
}

// 添加一个新的hash元素:新元素插入到链表头
void addNewEntry(K key, V value, int hash, int index) {
table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]);
}

HashMapEntry(K key, V value, int hash, HashMapEntry<K, V> next) {
this.key = key;
this.value = value;
this.hash = hash;
this.next = next;
}

4.get函数--相对put函数更简单
    public V get(Object key) {
...


        // Doug Lea's supplemental secondaryHash function (inlined).
        // Replace with Collections.secondaryHash when the VM is fast enough (http://b/8290590).
        int hash = key.hashCode();
        hash ^= (hash >>> 20) ^ (hash >>> 12);
        hash ^= (hash >>> 7) ^ (hash >>> 4);


        HashMapEntry<K, V>[] tab = table;
// 通过hash找到链表,并遍历链表每个元素,找到key对应value
        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
                e != null; e = e.next) {
            K eKey = e.key;
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                return e.value;
            }
        }
        return null;
    }

5.remove函数
/*
从链表中删除一个元素
*/
    @Override public V remove(Object key) {
        int hash = secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        int index = hash & (tab.length - 1);
        for (HashMapEntry<K, V> e = tab[index], prev = null;
                e != null; prev = e, e = e.next) {
            if (e.hash == hash && key.equals(e.key)) {
                if (prev == null) {
                    tab[index] = e.next;
                } else {
                    prev.next = e.next;
                }
                modCount++;
                size--;
                postRemove(e); // 通知子类,父类删除了该元素.  LinkedHashMap有实现该函数
                return e.value;
            }
        }
        return null;
    }






0 0
原创粉丝点击