Quantcast
Channel: User raptortech97 - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 22

Hash table implementation in Java

$
0
0

For class, I was asked to write a (linear probing) hash table in Java. (I was also asked to write a linear-chaining hash table, which is why I named this one HashtableB as opposed to just Hashtable.) I'm think my code is correct, but please tell me if I've messed up.

Primarily, though, my questions are:

  • Is my style (e.g. naming conventions, whitespace, line length, etc.) correct?
  • Do I have too few comments? Too many?
  • I've heard about Javadocs. Should I be using that? What would that look like?
  • Is my code clear and concise?
  • Is correctly object-oriented (e.g., should I have getters and setters for Pair)?
  • Am I using generics correctly?
  • Should I only be importing the specific parts of the standard libraries, or is importing java.utils.* okay?

The ST<K, V> interface is because I've written other symbol table implementations and wanted to be able to use/test them interchangeably.

HashtableB.java

import java.util.*;import java.lang.reflect.Array;// A linear-probing hash table implementationpublic class HashtableB<K, V> implements ST<K, V> {    private static final int MIN_CAP = 11; // The minimum size of the array; when smaller than this, no down-sizing will occur.    private Pair[] arr; // The array holding all the key/value pairs    private int size; // The current number of elements.    private int cap; // Current capacity of the array.    private double max; // determines how full the array can get before resizing occurs; default 1/2    private double min; // determines how empty the array can get before resizing occurs; default 3/4    private double set; // determines how full the array should be made when resizing; default 1/4    // Primary constructor.    // Set determines how full the array should be made when resizing    // Maximum determines how full the array can get before resizing occurs    // Minimum determines how empty the array can get before resizing occurs    public HashtableB(double maximum, double minimum, double set){        assert set < maximum && maximum < 1;        assert 0 < minimum && minimum < set;        size = 0;        cap = MIN_CAP;        max = maximum;        min = minimum;        this.set = set;        arr = (Pair[]) Array.newInstance(Pair.class, cap); // Make the new array;    }    // Default the set-size ratio to 1/2    public HashtableB(double maximum, double minimum){        this(maximum, minimum, 0.5);    }    // Default the max-size ratio to 3/4 and the min-size ratio to 1/4.    public HashtableB(){        this(0.75, 0.25);    }    // Get the given key.    public V get(K key){        assert key != null;        // Find the key.        int i = hash(key) % cap;        while(!key.equals(arr[i].k)){            i = (i+1) % cap;        }        return arr[i]==null? null : arr[i].v; // If there's nothing there, return null. Otherwise, return the value.    }    // Sets the given key to the given value.    public void put(K key, V val){        assert key != null;        int i = hash(key) % cap;        while (arr[i]!=null && !key.equals(arr[i].k)) {            i = (i+1) % cap;        }        if(arr[i] == null) // If we are putting a new key in, increase the size.            size++;        arr[i] = new Pair(key, val);        resize(); // If we need to resize, do so.    }    // A hash of the key. I used the absolute value of the key's hashcode so that I didn't get weird negative indices.    private int hash(K key){        return Math.abs(key.hashCode());    }    // Resize the array if necessary.    private void resize(){        if(!((size<cap*min && cap>MIN_CAP) || size>cap*max)){            return;        }        int newcap = (int) (size/set); // The size of the new array        @SuppressWarnings("unchecked")        Pair[] a = (Pair[]) Array.newInstance(Pair.class, newcap); // Make the new array        for(int j=0; j<cap; j++){            Pair q = arr[j];            if(q==null)                continue;            int i = hash(q.k) % newcap;            while (a[i]!=null && !q.k.equals(a[i].k)) {                i = (i+1) % newcap; // get next index            }            a[i] = q;        }        this.arr = a;        this.cap = newcap;    }    // In here for development purposes only.    public boolean checkSize(){        int x = 0;        for(int i=0; i<cap; i++){            if(arr[i] != null)                x++;        }        return x == size;    }    // Return the number of elements currently contained in this hashtable.    public int size(){        return size;    }    // Return a list of all the keys currently contained in this hashtable.    public Set<K> getAll(){        Set<K> set = new HashSet<K>(size);        for(Pair p : arr)            if(p != null)                set.add(p.k);        return set;    }    // Remove the given key from the hashtable.       public void delete(K key){        assert key != null;        List<Pair> pairs = new ArrayList<Pair>();        // Find our key.        int i = hash(key) % cap;        while(arr[i]!=null && !key.equals(arr[i].k)){            i = (i+1) % cap;            if(arr[i] == null)                System.out.printf("Delete could not find key %s %n", key.toString());        }        // Remove all the keys that could have been "forced over" by this key.        while(arr[i] != null){            pairs.add(arr[i]);            arr[i] = null;            size--;            i = (i+1) % cap;        }        pairs.remove(0); // Remove the key we're deleting.        for(Pair p : pairs)            this.put(p.k, p.v); // Put the rest back in the hashtable.    }    public String toString(){        return String.format("Hashtable(%.2f, %.2f, %.2f)", max, min, set);    }    // A key-value pair.    class Pair{        K k;        V v;        public Pair(K key, V val){            k = key;            v = val;        }    }}

ST.java

import java.util.*;// Symbol table matching keys (of type K) with values (of type V).public interface ST<K, V> {    V get(K key); // Get the value associated with the given key.    void put(K key, V value); // Set the value associated with the given key. The key can be in the dictionary already or not.    void delete(K key); // Remove the value associated with the given key (this should decrement the size).    Set<K> getAll(); // Get all the keys in this symbol table.    int size(); // Get the number of elements currently in the symbol table.    boolean checkSize(); // For development only. Checks that the stored size and actual size match.}

Viewing all articles
Browse latest Browse all 22

Latest Images

Trending Articles





Latest Images