简体   繁体   English

如何修复 java 哈希表断言错误?

[英]how to fix java hashtable assertion error?

I have to implement a Hashtable that passes set tests for coursework, i have managed to pass all the tests but two and cannot figure out why they are not passing.我必须实现一个通过课程设置测试的哈希表,我已经设法通过了所有测试,但只有两个,但无法弄清楚为什么它们没有通过。 Both tests give an assertion error.两个测试都给出断言错误。 They test the get and put methods.他们测试 get 和 put 方法。

bellow is the entirety of the hashtable code as i believe the error could be in another method.下面是整个哈希表代码,因为我相信错误可能出在另一种方法中。

Hashtable code:哈希表代码:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;

public class Hashtable<V> {

private Object[] arr; //an array of Pair objects, where each pair contains the key and value stored in the hashtable
private int max; //the size of arr. This should be a prime number
private int itemCount; //the number of items stored in arr
private final double maxLoad = 0.6; //the maximum load factor

public static enum PROBE_TYPE {
    LINEAR_PROBE, QUADRATIC_PROBE, DOUBLE_HASH;
}

PROBE_TYPE probeType; //the type of probe to use when dealing with collisions
private final BigInteger DBL_HASH_K = BigInteger.valueOf(8);

/**
 * Create a new Hashtable with a given initial capacity and using a given probe type
 * @param initialCapacity
 * @param pt
 */
public Hashtable(int initialCapacity, PROBE_TYPE pt) {
    max = nextPrime(initialCapacity);
    probeType = pt ;
    arr = new Object[max];
}

/**
 * Create a new Hashtable with a given initial capacity and using the default probe type
 * @param initialCapacity
 */
public Hashtable(int initialCapacity) {
    max = nextPrime(initialCapacity);
    probeType = PROBE_TYPE.LINEAR_PROBE;
    arr = new Object[max];
}

/**
 * Store the value against the given key. If the loadFactor exceeds maxLoad, call the resize 
 * method to resize the array. the If key already exists then its value should be overwritten.
 * Create a new Pair item containing the key and value, then use the findEmpty method to find an unoccupied 
 * position in the array to store the pair. Call findEmmpty with the hashed value of the key as the starting
 * position for the search, stepNum of zero and the original key.
 * containing   
 * @param key
 * @param value
 */

public void put(String key, V value) {  
    int i = hash(key);
    int finalPos = findEmpty(i,1, key);
    
    if (this.getLoadFactor() > this.maxLoad) {
        this.resize();
    }
    
    if (!hasKey(key)) {
        itemCount++;
    }
    
    arr[finalPos] = new Pair(key, value);   
}

/**
 * Get the value associated with key, or return null if key does not exists. Use the find method to search the
 * array, starting at the hashed value of the key, stepNum of zero and the original key.
 * @param key
 * @return
 */
public V get(String key) {
    int i = hash(key);
    
    if( arr[i] == null) {
        return null;
    } else {return find(hash(key),key,0);}
}

/**
 * Return true if the Hashtable contains this key, false otherwise 
 * @param key
 * @return
 */
public boolean hasKey(String key) {
    if (find(hash(key),key,0) == null) {
        return false;
    }else {
        return true;
    }
}

/**
 * Return all the keys in this Hashtable as a collection
 * @return
 */
public Collection<String> getKeys() {
    ArrayList<String> collection = new ArrayList<String>();
    for(int i =0;i<arr.length;i++) {
        if(arr[i] != null) {
            Pair p = (Pair) arr[i];
            collection.add(p.key);
        }
    }
    return collection;
}

/**
 * Return the load factor, which is the ratio of itemCount to max
 * @return
 */
public double getLoadFactor() {
    return itemCount / (double) max;
}

/**
 * return the maximum capacity of the Hashtable
 * @return
 */
public int getCapacity() {
    return this.max;
}

/**
 * Find the value stored for this key, starting the search at position startPos in the array. If
 * the item at position startPos is null, the Hashtable does not contain the value, so return null. 
 * If the key stored in the pair at position startPos matches the key we're looking for, return the associated 
 * value. If the key stored in the pair at position startPos does not match the key we're looking for, this
 * is a hash collision so use the getNextLocation method with an incremented value of stepNum to find 
 * the next location to search (the way that this is calculated will differ depending on the probe type 
 * being used). Then use the value of the next location in a recursive call to find.
 * @param startPos
 * @param key
 * @param stepNum
 * @return
 */
private V find(int startPos, String key, int stepNum) {
    Pair p = (Pair) arr[startPos];
    if(p == null) {
        return null;
        
    }else if (p.key.equals(key)) {
        return p.value;
        
    }else {
        stepNum++;
        int nextLocation = getNextLocation(startPos, stepNum, key);
        return find(nextLocation, key , stepNum);
    }
}

/**
 * Find the first unoccupied location where a value associated with key can be stored, starting the
 * search at position startPos. If startPos is unoccupied, return startPos. Otherwise use the getNextLocation
 * method with an incremented value of stepNum to find the appropriate next position to check 
 * (which will differ depending on the probe type being used) and use this in a recursive call to findEmpty.
 * @param startPos
 * @param stepNum
 * @param key
 * @return
 */
private int findEmpty(int startPos, int stepNum, String key) {
    if (arr[startPos] == null || ((Pair) arr[startPos]).key.equals(key)) {
        return startPos;
    }else {
        stepNum++;
        int nextPos = getNextLocation(startPos,stepNum,key);
        return findEmpty(nextPos,stepNum,key);
    }       
}

/**
 * Finds the next position in the Hashtable array starting at position startPos. If the linear
 * probe is being used, we just increment startPos. If the double hash probe type is being used, 
 * add the double hashed value of the key to startPos. If the quadratic probe is being used, add
 * the square of the step number to startPos.
 * @param i
 * @param stepNum
 * @param key
 * @return
 */
private int getNextLocation(int startPos, int stepNum, String key) {
    int step = startPos;
    switch (probeType) {
    case LINEAR_PROBE:
        step++;
        break;
    case DOUBLE_HASH:
        step += doubleHash(key);
        break;
    case QUADRATIC_PROBE:
        step += stepNum * stepNum;
        break;
    default:
        break;
    }
    return step % max;
}

/**
 * A secondary hash function which returns a small value (less than or equal to DBL_HASH_K)
 * to probe the next location if the double hash probe type is being used
 * @param key
 * @return
 */
private int doubleHash(String key) {
    BigInteger hashVal = BigInteger.valueOf(key.charAt(0) - 96);
    for (int i = 0; i < key.length(); i++) {
        BigInteger c = BigInteger.valueOf(key.charAt(i) - 96);
        hashVal = hashVal.multiply(BigInteger.valueOf(27)).add(c);
    }
    return DBL_HASH_K.subtract(hashVal.mod(DBL_HASH_K)).intValue();
}

/**
 * Return an int value calculated by hashing the key. See the lecture slides for information
 * on creating hash functions. The return value should be less than max, the maximum capacity 
 * of the array
 * @param key
 * @return
 */
private int hash(String key) {
    int hashVal = key.charAt(0);
    for(int i=0; i<key.length();i++) {
        int c = key.charAt(i);
        hashVal =(hashVal * 27 +c) % max;
    }
    return hashVal;
}

/**
 * Return true if n is prime
 * @param n
 * @return
 */
private boolean isPrime(int n) {
    if(n<=2) return true;
    if(n % 2 == 0) return false;
    for(int i=3; i*i<n; i+=2) {
        if(n % i == 0) return false;
    }
    return true;
}

/**
 * Get the smallest prime number which is larger than n
 * @param n
 * @return
 */
private int nextPrime(int n) {
    if(isPrime(n)) {
        return n;
    }else {
        n++;
        return nextPrime(n);
    }
}

/**
 * Resize the hashtable, to be used when the load factor exceeds maxLoad. The new size of
 * the underlying array should be the smallest prime number which is at least twice the size
 * of the old array.
 */
private void resize() {
        int tableSize = nextPrime(max*2);
        Object[] oldArr = arr;
        arr = new Object[tableSize];
        itemCount = 0;
        max = tableSize;
        for (int i=0;i<oldArr.length;i++) {
            if(oldArr[i] != null) {
                Pair p = (Pair) oldArr[i];
                put(p.key, p.value);
            }
            
        }
}


/**
 * Instances of Pair are stored in the underlying array. We can't just store
 * the value because we need to check the original key in the case of collisions.
 * @author jb259
 *
 */
private class Pair {
    private String key;
    private V value;

    public Pair(String key, V value) {
        this.key = key;
        this.value = value;
    }
}

} }

Tests:测试:

@Test
public void testInsert() {
    Hashtable<Boolean> h = new Hashtable<>(1000, PROBE_TYPE.DOUBLE_HASH);
    for(int i=0;i<2000;i++) {
        for(int j=2000;j>0;j--) {
            h.put(i+":"+j, true);
        }
    }
    
    for(int i=0;i<2000;i++) {
        for(int j=2000;j>0;j--) {
            assertTrue(h.hasKey(i+":"+j));
        }
    }
}

    @Test
public void testGet() {
    Hashtable<String> h = new Hashtable<>(9);
    int c = 0;
    for(int i=0;i<10;i++) {
        for(int j=10;j>0;j--) {
            h.put(i+":"+j, j+":"+i);
            c++;
        }
    }
    for(int i=0;i<10;i++) {
        for(int j=10;j>0;j--) {
            assertEquals(h.get(i+":"+j), j+":"+i);
        }
    }
}

many thanks for your help!!非常感谢您的帮助!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM