I'm trying to write some functions to display the average amount of buckets being used and the average chain length in my hashtable. I dont know how to measure these things.
public Double bucketUsagePercentage(){
}
public Double avgChainLength(){
}
public void printStats(){
System.out.println("LoadFactor: " + getTableLoad());
}
As already mentioned, you could actually wrap the Hashtable and then keep track of the inserted Object hashcodes + dynamically calculate the number of available buckets. But, assuming you know the loadfactor (default 0.75) you can create static tools to "measure" any existing Hashtable (you can easily alter it to work for HashSets as well).
*Just to highlight that due to the initial capacity requirement, results may not be 100% accurate at the very beginning, because initial buckets are fixed until rehashing is required.
import java.util.Hashtable;
public class HashMetrics {
public static double bucketUsagePercentage(Hashtable<?,?> a, double loadfactor) {
int bucketSize = getBucketSize(a, loadfactor);
int[] bucketFrequency = new int[bucketSize];
for (Object k : a.keySet()) {
bucketFrequency[k.hashCode() % bucketSize]++;
}
int counter = 0;
for (int i : bucketFrequency) {
if (i > 0) counter++;
}
return (double)counter / bucketSize;
}
//skip empty buckets (very similar to previous function, last line is only changed)
public static double averageChainLength(Hashtable<?,?> a, double loadfactor) {
int bucketSize = getBucketSize(a, loadfactor);
int[] bucketFrequency = new int[bucketSize];
for (Object k : a.keySet()) {
bucketFrequency[k.hashCode() % bucketSize]++;
}
int counter = 0;
for (int i : bucketFrequency) {
if (i > 0) counter++;
}
return (double)a.size() / counter;
}
public static int log2(int number) {
if(number == 0)
return 0;
return 31 - Integer.numberOfLeadingZeros(number);
}
public static int getBucketSize(Hashtable<?,?> a, double loadFactor) {
int n = a.size();
int bucketSize = 2 << log2(n);
if (bucketSize * loadFactor <= n) {
bucketSize <<= 1;
}
return bucketSize;
}
}