Subversion Repositories programming

Rev

Rev 5 | Blame | Last modification | View Log | RSS feed

//import chap09.list03.Map;

import java.io.*;
import java.util.*;

public class HashTable implements Map {  // open addressing
    private Entry[] entries;
    private int size, used;
    private float loadFactor;
    private final Entry NIL = new Entry(null,null);  // dummy

    public HashTable(int capacity, float loadFactor) {
        entries = new Entry[capacity];
        this.loadFactor = loadFactor; }

    public HashTable(int capacity) {
        this(capacity,0.75F);}

    public HashTable() {
        this(101); }

    public Object get(Object key) {
        int h=hash(key);
        for (int i=0; i<entries.length; i++) {
            int j = nextProbe(h,i);
            Entry entry=entries[j];
            if (entry==null) break;
            if (entry==NIL) continue;
            if (entry.key.equals(key)) return entry.value;  // success
        }
        return null;  // failure: key not found
    }
    
    public Object put(Object key, Object value) {
        if (used>loadFactor*entries.length) rehash();
        int h=hash(key);
        for (int i=0; i<entries.length; i++) {
            int j = nextProbe(h,i);
            Entry entry=entries[j];
            if (entry==null) {
                entries[j] = new Entry(key,value);
                ++size;
                ++used;
                return null;  // insertion success
            }
            if (entry==NIL) continue;
            if (entry.key.equals(key)) {
                Object oldValue=entry.value;
                entries[j].value = value;
                return oldValue;  // update success
            }
        }
        return null;  // failure: table overflow
    }

    public Object remove(Object key) {
        int h=hash(key);
        for (int i=0; i<entries.length; i++) {
            int j = nextProbe(h,i);
            Entry entry=entries[j];
            if (entry==null) break;
            if (entry==NIL) continue;
            if (entry.key.equals(key)) {
                Object oldValue=entry.value;
                entries[j] = NIL;
                --size;
                return oldValue;  // success
            }
        }
        return null;  // failure: key not found
    }

    public int size() {
        return size;
    }

    private class Entry {
        Object key, value;
        Entry(Object k, Object v) { key=k; value=v; }
    }

    private int hash(Object key) {
        if (key==null) throw new IllegalArgumentException();
        return (key.hashCode() & 0x7FFFFFFF) % entries.length;
    }

    private int nextProbe(int h, int i) {
        return (h + i)%entries.length;      // Linear Probing
    }

    private void rehash() {
        Entry[] oldEntries = entries;
        entries = new Entry[2*oldEntries.length+1];
        for (int k=0; k<oldEntries.length; k++) {
            Entry entry=oldEntries[k];
            if (entry==null || entry==NIL) continue;
            int h=hash(entry.key);
            for (int i=0; i<entries.length; i++) {
                int j = nextProbe(h,i);
                if (entries[j]==null) {
                    entries[j] = entry;
                    break;
                }
            }
        }
        used = size;
    }
}