1

So I am trying to detect for collisions in my linear method, which is hashing the keys of my hash map studentMap. I have the basic function for the linear probing, however I am struggling to detect if a key is already there (and therefore + 1). So far this code does not work - it does not check the key from my map studentMap as to whether it is there or not. Any help much appreciated! I have removed some of the other hash methods to reduce the size of this code as they are irrelevant.

 public class Main  {
   Student student;
   public static boolean vartrue;
   HashMap next;
    public HashMap<String,Student> studentMap;
    public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException {
        HashMap<String, String> studentMap = new HashMap<>(16, 0.75f);
        //et keys and value
        studentMap.keySet().forEach((key) -> {
            String value = studentMap.get(key);
            System.out.println("Key = " + key + ", Value = " + value);
        });   
        //adding values to array
        studentMap.put("16012804", "Jennifer");
        studentMap.put("13747732", "Beatrice");
        studentMap.put("14056983", "Mavis");
        studentMap.put("16013464", "Geoffrey");
        studentMap.put("14058392", "Bob");
        studentMap.put("15405833", "Bill");
        studentMap.put("14058039", "Gertrude");
        studentMap.put("13056496", "Dorothy");
        //iterating through the array
        Set set = studentMap.entrySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()) {
            Map.Entry mapentry = (Map.Entry)iterator.next();
            System.out.print("Key is: "+ mapentry.getKey() + " & Value is: ");
            System.out.println(mapentry.getValue());
        }
       //Get values based on key
        String var= studentMap.get("16012804");
        System.out.println("Value at index 1 is: "+var);
        // Remove values based on key
        studentMap.remove("16012804");
        System.out.println("Map key and values after removal:");
        Set set2 = studentMap.entrySet();
        Iterator iterator2 = set2.iterator();
        while(iterator2.hasNext()) {
          Map.Entry mapentry2 = (Map.Entry)iterator2.next();
          System.out.print("Key is: "+mapentry2.getKey() + " & Value is: ");
          System.out.println(mapentry2.getValue());
        }
        Set keyset = studentMap.keySet();
        System.out.println("Key set values are:" + keyset);
        boolean val = studentMap.isEmpty();
        System.out.println("Is hash map empty: " + val);
        //get values
        Collection<String> values = studentMap.values();
        System.out.println("Map values = " + values);
        //size of table
        System.out.println("Size of the Hashtable: " + studentMap.size());
        //initial capacity
        System.out.println("Initial Capacity: " + 16);
        //capacity of map
        System.out.println("Map capacity: " +  mapcapacity(studentMap));
        //load factor
        System.out.println("Load Factor: " + loadFactor(studentMap));

        //linear probing
        System.out.println("...");
        System.out.println("Hash Value(\"Jennifer\")="+ linear(studentMap, "16012804"));
        System.out.println("Hash Value(\"Mavis\")="+ linear(studentMap, "14056983"));
        System.out.println("Hash Value(\"Geoffrey\")="+ linear(studentMap, "16013464"));
        System.out.println("Hash Value(\"Bill\")="+ linear(studentMap, "15405833"));
        System.out.println("Hash Value(\"Gertrude\")="+ linear(studentMap, "14058039"));
        System.out.println("Hash Value(\"Beatrice\")="+ linear(studentMap, "13747732"));
        System.out.println("Hash Value(\"Bob\")="+ linear(studentMap, "14058392"));

         if (vartrue = true)
             {
             Map<String, String> map1 = new HashMap<>(mapcapacity(studentMap) * 2);
             map1.putAll(studentMap); 
             //capacity of the new hash map. (reflection)
             System.out.println("Map 1 mappings= " + map1);
             Field tableField = HashMap.class.getDeclaredField("table");
             tableField.setAccessible(true);
             Object[] table = (Object[]) tableField.get(map1);
             System.out.println("Size of Map 1: ");
             System.out.println(table == null ? 0 : table.length);
             }

        }
    //when to increase the hashmap size is calculated by capacity of hashmap divided by load factor:
    public static double loadFactor(Map studentMap){
    double count = studentMap.size();
        double load = count/mapcapacity(studentMap);
        return load;
    }
    //if the size of the map is greater than the map capacity * load factor - then double the size of map. 
    public static Integer mapcapacity(Map studentMap){
        //default capacity and load factor
       Integer initCapacity= 11;
       float loadFactor=0.75f;
       boolean capacityFound=false;
        Integer capacity=initCapacity;
        Integer size=studentMap.size();
        while(!capacityFound){
            if(size>capacity*loadFactor){
                //increase capacity 
                capacity=capacity * 2;  
                vartrue = true; 
            }
            else {
                capacityFound=true;   
            }
        }
        return capacity;
    }




    //linear probing
    public static int hashThis(String key, Map studentMap) {
        return key.hashCode()& 0x7fffffff % mapcapacity(studentMap); 
    }
    public static int linear(Map studentMap, String key){
    String value = studentMap.get(key).toString();
    int counter = 0;
    int hash = hashThis(key, studentMap);
    if (value != null)
    {
    hash = (hash + 1) % mapcapacity(studentMap);
    counter ++;
    }
    else{
        return 0;
    }
     return hash;
     }


}
pickle
  • 11
  • 3

1 Answers1

0

As far as I understand, you've decided to implement your own hash map manually, rather than using java.util.HashMap , which is already running in a linear probing manner. In that case, the source of java.util.HashMap might be a big hint. From "grepcode.com" site, I found source codes of put(K key, V value) method of java.util.HashMap as follows;

public V put(K key, V value) {
     ... // null check on key : omitted

     int hash = hash(key.hashCode());
     int i = indexFor(hash, table.length);

     for (Entry<K,V> e = table[i]; e != null; e = e.next) {
         Object k;
         if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
             ... // if the same key already exists, return the old value : omitted
         }
     }
     modCount++;
     addEntry(hash, key, value, i);
     return null;
}

Before addEntry() is called, for statement is iterated searching for an available space. (That is, when exiting for loop, i indicates an index for an available space for the new entry.) You may also check get(), the dual method of put(), for better understanding.

I think, the most important thing here for you is that java.util.HashMap does NOT seem to "change the hashcode" for linear probing. This is the main difference from your approach since linear() in your code seems to adjust the hash for a given key, everytime when the space for the hash value is already taken.

In addition, linear() in your code does not use iteration for searching a free space, but mapcapacity() does for size extention. This might cause mutiple space adjustment for a single key insertion, so does not seem like an efficient way for linear probling.

In summary, I'd like to suggest to check the source codes of of java.util.HashMap or related classes ;)

fcmonoid
  • 33
  • 1
  • 6