22
33import java .util .LinkedList ;
44
5- // implementation of generic hashmaps using array of Linked Lists
6-
5+ /**
6+ * A generic implementation of a hash map using an array of linked lists for collision resolution.
7+ * This class provides a way to store key-value pairs efficiently, allowing for average-case
8+ * constant time complexity for insertion, deletion, and retrieval operations.
9+ *
10+ * <p>
11+ * The hash map uses separate chaining for collision resolution. Each bucket in the hash map is a
12+ * linked list that stores nodes containing key-value pairs. When a collision occurs (i.e., when
13+ * two keys hash to the same index), the new key-value pair is simply added to the corresponding
14+ * linked list.
15+ * </p>
16+ *
17+ * <p>
18+ * The hash map automatically resizes itself when the load factor exceeds 0.75. The load factor is
19+ * defined as the ratio of the number of entries to the number of buckets. When resizing occurs,
20+ * all existing entries are rehashed and inserted into the new buckets.
21+ * </p>
22+ *
23+ * @param <K> the type of keys maintained by this hash map
24+ * @param <V> the type of mapped values
25+ */
726public class GenericHashMapUsingArray <K , V > {
827
9- private int size ; // n (total number of key-value pairs)
10- private LinkedList <Node >[] buckets ; // N = buckets.length
11- private float lf = 0.75f ;
28+ private int size ; // Total number of key-value pairs
29+ private LinkedList <Node >[] buckets ; // Array of linked lists (buckets) for storing entries
1230
31+ /**
32+ * Constructs a new empty hash map with an initial capacity of 16.
33+ */
1334 public GenericHashMapUsingArray () {
1435 initBuckets (16 );
1536 size = 0 ;
1637 }
1738
18- // load factor = 0.75 means if we need to add 100 items and we have added
19- // 75, then adding 76th item it will double the size, copy all elements
20- // & then add 76th item.
21-
39+ /**
40+ * Initializes the buckets for the hash map with the specified number of buckets.
41+ *
42+ * @param n the number of buckets to initialize
43+ */
2244 private void initBuckets (int n ) {
2345 buckets = new LinkedList [n ];
2446 for (int i = 0 ; i < buckets .length ; i ++) {
2547 buckets [i ] = new LinkedList <>();
2648 }
2749 }
2850
51+ /**
52+ * Associates the specified value with the specified key in this map.
53+ * If the map previously contained a mapping for the key, the old value is replaced.
54+ *
55+ * @param key the key with which the specified value is to be associated
56+ * @param value the value to be associated with the specified key
57+ */
2958 public void put (K key , V value ) {
3059 int bucketIndex = hashFunction (key );
3160 LinkedList <Node > nodes = buckets [bucketIndex ];
32- for (Node node : nodes ) { // if key present => update
61+ // Update existing key's value if present
62+ for (Node node : nodes ) {
3363 if (node .key .equals (key )) {
3464 node .value = value ;
3565 return ;
3666 }
3767 }
3868
39- // key is not present => insert
69+ // Insert new key-value pair
4070 nodes .add (new Node (key , value ));
4171 size ++;
4272
43- if ((float ) size / buckets .length > lf ) {
73+ // Check if rehashing is needed
74+ // Load factor threshold for resizing
75+ float loadFactorThreshold = 0.75f ;
76+ if ((float ) size / buckets .length > loadFactorThreshold ) {
4477 reHash ();
4578 }
4679 }
4780
48- // tells which bucket to go to
81+ /**
82+ * Returns the index of the bucket in which the key would be stored.
83+ *
84+ * @param key the key whose bucket index is to be computed
85+ * @return the bucket index
86+ */
4987 private int hashFunction (K key ) {
5088 return Math .floorMod (key .hashCode (), buckets .length );
5189 }
5290
91+ /**
92+ * Rehashes the map by doubling the number of buckets and re-inserting all entries.
93+ */
5394 private void reHash () {
54- System .out .println ("Rehashing!" );
55- LinkedList <Node >[] old = buckets ;
56- initBuckets (old .length * 2 );
95+ LinkedList <Node >[] oldBuckets = buckets ;
96+ initBuckets (oldBuckets .length * 2 );
5797 this .size = 0 ;
5898
59- for (LinkedList <Node > nodes : old ) {
99+ for (LinkedList <Node > nodes : oldBuckets ) {
60100 for (Node node : nodes ) {
61101 put (node .key , node .value );
62102 }
63103 }
64104 }
65105
106+ /**
107+ * Removes the mapping for the specified key from this map if present.
108+ *
109+ * @param key the key whose mapping is to be removed from the map
110+ */
66111 public void remove (K key ) {
67112 int bucketIndex = hashFunction (key );
68113 LinkedList <Node > nodes = buckets [bucketIndex ];
@@ -74,14 +119,28 @@ public void remove(K key) {
74119 break ;
75120 }
76121 }
77- nodes .remove (target );
78- size --;
122+
123+ if (target != null ) {
124+ nodes .remove (target );
125+ size --;
126+ }
79127 }
80128
129+ /**
130+ * Returns the number of key-value pairs in this map.
131+ *
132+ * @return the number of key-value pairs
133+ */
81134 public int size () {
82135 return this .size ;
83136 }
84137
138+ /**
139+ * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
140+ *
141+ * @param key the key whose associated value is to be returned
142+ * @return the value associated with the specified key, or null if no mapping exists
143+ */
85144 public V get (K key ) {
86145 int bucketIndex = hashFunction (key );
87146 LinkedList <Node > nodes = buckets [bucketIndex ];
@@ -96,7 +155,6 @@ public V get(K key) {
96155 @ Override
97156 public String toString () {
98157 StringBuilder builder = new StringBuilder ();
99-
100158 builder .append ("{" );
101159 for (LinkedList <Node > nodes : buckets ) {
102160 for (Node node : nodes ) {
@@ -106,19 +164,37 @@ public String toString() {
106164 builder .append (", " );
107165 }
108166 }
167+ // Remove trailing comma and space
168+ if (builder .length () > 1 ) {
169+ builder .setLength (builder .length () - 2 );
170+ }
109171 builder .append ("}" );
110172 return builder .toString ();
111173 }
112174
175+ /**
176+ * Returns true if this map contains a mapping for the specified key.
177+ *
178+ * @param key the key whose presence in this map is to be tested
179+ * @return true if this map contains a mapping for the specified key
180+ */
113181 public boolean containsKey (K key ) {
114182 return get (key ) != null ;
115183 }
116184
185+ /**
186+ * A private class representing a key-value pair (node) in the hash map.
187+ */
117188 public class Node {
118-
119189 K key ;
120190 V value ;
121191
192+ /**
193+ * Constructs a new Node with the specified key and value.
194+ *
195+ * @param key the key of the key-value pair
196+ * @param value the value of the key-value pair
197+ */
122198 public Node (K key , V value ) {
123199 this .key = key ;
124200 this .value = value ;
0 commit comments