@@ -16,24 +16,25 @@ class HashTableNode<K, V> {
1616public class HashTable <K , V > {
1717 Object [] buckets ;
1818 float loadFactor = 0.75f ; // The maximum load factor
19- ToIntFunction <Integer > hashFunction = k -> k % this .buckets . length ; // h(k)
19+ ToIntFunction <Integer > hashFunction = k -> k % this .capacity ; // h(k)
2020 int length ;
21+ int capacity ;
2122
2223 public HashTable () {
23- this .buckets = new Object [1 << 4 ]; // Start with 16 buckets by default
24+ this .buckets = new Object [this . capacity = 16 ];
2425 this .length = 0 ;
2526 }
2627
2728 public HashTable (int initialCapacity ) {
28- this .buckets = new Object [initialCapacity ];
29+ this .buckets = new Object [this . capacity = initialCapacity ];
2930 this .length = 0 ;
3031 }
3132
3233 public HashTable (int initialCapacity , float loadFactor ) {
3334 if (loadFactor <= 0 )
3435 throw new IllegalArgumentException ("Illegal load factor: " + loadFactor );
3536
36- this .buckets = new Object [initialCapacity ];
37+ this .buckets = new Object [this . capacity = initialCapacity ];
3738 this .loadFactor = loadFactor ;
3839 this .length = 0 ;
3940 }
@@ -43,7 +44,7 @@ public int getLength() {
4344 }
4445
4546 public int getCapacity () {
46- return this .buckets . length ;
47+ return this .capacity ;
4748 }
4849
4950 public ToIntFunction <Integer > getHashFunction () {
@@ -83,7 +84,7 @@ private boolean put(HashTableNode<K, V> newNode, Object[] buckets) {
8384 }
8485
8586 public void put (K key , V value ) {
86- if ((this .length + 1 ) / this .buckets . length > this .loadFactor )
87+ if ((float ) ( this .length + 1 ) / this .capacity > this .loadFactor )
8788 this .expand ();
8889
8990 if (this .put (new HashTableNode <K , V >(key , value , null ), this .buckets ))
@@ -111,6 +112,7 @@ public boolean remove(K key) {
111112 node = node .next ;
112113 }
113114
115+ // TODO: this.length--;
114116 return false ;
115117 }
116118
@@ -129,28 +131,49 @@ public V get(K key) {
129131 }
130132
131133 private void rehash (int newCapacity ) {
132- Object [] newBuckets = new Object [newCapacity ];
134+ Object [] newBuckets = new Object [this . capacity = newCapacity ];
133135
134136 for (Object bucket : this .buckets ) {
135137 HashTableNode <K , V > node = (HashTableNode <K , V >) bucket ;
136138
137139 if (node == null )
138140 continue ;
139141 else
140- while ( node . next != null ) {
142+ do {
141143 this .put (node , newBuckets );
142144 node = node .next ;
143- }
145+ } while ( node != null );
144146 }
145147
146148 this .buckets = newBuckets ;
147149 }
148150
149151 private void expand () {
150- this .rehash (this .buckets . length * 2 );
152+ this .rehash (this .capacity * 2 );
151153 }
152154
153155 public void shrink (float minimumLoadFactor ) {
154156 this .rehash ((int ) Math .ceil (this .length / minimumLoadFactor ));
155157 }
158+
159+ public float measureClustering () {
160+ int squaresSum = 0 ;
161+
162+ for (Object bucket : this .buckets ) {
163+ int numElements = 0 ; // Number of elements in this bucket
164+ HashTableNode <K , V > node = (HashTableNode <K , V >) bucket ;
165+
166+ while (node != null ) {
167+ numElements ++;
168+ node = node .next ;
169+ }
170+
171+ squaresSum += Math .pow (numElements , 2 );
172+ }
173+
174+ int m = this .capacity ;
175+ float n = this .length ;
176+
177+ return (m / (n - 1 )) * (squaresSum / n - 1 );
178+ }
156179}
0 commit comments