1111@ SuppressWarnings ("rawtypes" )
1212public class HashMap <K , V > {
1313 private final int hashSize ;
14+ private int currentSize ; // Correctly track the total number of key-value pairs
1415 private final LinkedList <K , V >[] buckets ;
1516
1617 /**
@@ -21,6 +22,7 @@ public class HashMap<K, V> {
2122 @ SuppressWarnings ("unchecked" )
2223 public HashMap (int hashSize ) {
2324 this .hashSize = hashSize ;
25+ this .currentSize = 0 ;
2426 // Safe to suppress warning because we are creating an array of generic type
2527 this .buckets = new LinkedList [hashSize ];
2628 for (int i = 0 ; i < hashSize ; i ++) {
@@ -37,9 +39,10 @@ public HashMap(int hashSize) {
3739 */
3840 private int computeHash (K key ) {
3941 if (key == null ) {
40- return 0 ; // Use a special bucket (e.g., bucket 0) for null keys
42+ return 0 ; // Use bucket 0 for null keys
4143 }
4244 int hash = key .hashCode () % hashSize ;
45+ // Ensure the hash index is non-negative
4346 return hash < 0 ? hash + hashSize : hash ;
4447 }
4548
@@ -52,7 +55,12 @@ private int computeHash(K key) {
5255 */
5356 public void insert (K key , V value ) {
5457 int hash = computeHash (key );
55- buckets [hash ].insert (key , value );
58+ boolean keyExisted = buckets [hash ].insert (key , value );
59+
60+ // Only increment size if a new key was inserted (not an update)
61+ if (!keyExisted ) {
62+ currentSize ++;
63+ }
5664 }
5765
5866 /**
@@ -62,7 +70,12 @@ public void insert(K key, V value) {
6270 */
6371 public void delete (K key ) {
6472 int hash = computeHash (key );
65- buckets [hash ].delete (key );
73+ boolean deletedSuccessfully = buckets [hash ].delete (key );
74+
75+ // Only decrement size if deletion was successful
76+ if (deletedSuccessfully ) {
77+ currentSize --;
78+ }
6679 }
6780
6881 /**
@@ -73,8 +86,8 @@ public void delete(K key) {
7386 */
7487 public V search (K key ) {
7588 int hash = computeHash (key );
76- Node < K , V > node = buckets [ hash ]. findKey ( key );
77- return node != null ? node . getValue () : null ;
89+ // Changed LinkedList to return the value directly for better encapsulation
90+ return buckets [ hash ]. findValue ( key ) ;
7891 }
7992
8093 /**
@@ -87,80 +100,71 @@ public void display() {
87100 }
88101
89102 /**
90- * Clears the contents of the hash map by reinitializing each bucket.
103+ * Clears the contents of the hash map by reinitializing each bucket and resetting the size .
91104 */
92105 public void clear () {
93106 for (int i = 0 ; i < hashSize ; i ++) {
94107 buckets [i ] = new LinkedList <>();
95108 }
109+ currentSize = 0 ; // Reset size
96110 }
97111
98112 /**
99113 * Gets the number of key-value pairs in the hash map.
114+ * Corrected to return the stored 'currentSize' in O(1) time.
100115 *
101116 * @return the number of key-value pairs in the hash map
102117 */
103118 public int size () {
104- int size = 0 ;
105- for (int i = 0 ; i < hashSize ; i ++) {
106- size += buckets [i ].isEmpty () ? 0 : 1 ;
107- }
108- return size ;
119+ return currentSize ;
109120 }
110121
122+ // --- NESTED LINKED LIST CLASS (Collision Handler) ---
123+
111124 /**
112125 * A nested static class that represents a linked list used for separate chaining in the hash map.
113- *
114- * @param <K> the type of keys maintained by this linked list
115- * @param <V> the type of mapped values
116126 */
117127 public static class LinkedList <K , V > {
118128 private Node <K , V > head ;
119129
120130 /**
121131 * Inserts the specified key-value pair into the linked list.
122- * If the linked list is empty, the pair becomes the head.
123- * Otherwise, the pair is added to the end of the list.
132+ * If the key already exists, the value is updated.
124133 *
125134 * @param key the key to be inserted
126135 * @param value the value to be associated with the key
136+ * @return true if an existing key was updated, false if a new node was created.
127137 */
128- public void insert (K key , V value ) {
129- Node <K , V > existingNode = findKey (key );
138+ public boolean insert (K key , V value ) {
139+ Node <K , V > existingNode = findNode (key );
130140 if (existingNode != null ) {
131- existingNode .setValue (value ); // Update the value, even if it's null
141+ existingNode .setValue (value );
142+ return true ; // Key existed, value updated
132143 } else {
144+ Node <K , V > newNode = new Node <>(key , value );
133145 if (isEmpty ()) {
134- head = new Node <>( key , value ) ;
146+ head = newNode ;
135147 } else {
136- Node <K , V > temp = findEnd (head );
137- temp .setNext (new Node <>(key , value ));
148+ Node <K , V > temp = head ; // Start search from head
149+ while (temp .getNext () != null ) {
150+ temp = temp .getNext ();
151+ }
152+ temp .setNext (newNode );
138153 }
154+ return false ; // New key added
139155 }
140156 }
141157
142158 /**
143- * Finds the last node in the linked list.
144- *
145- * @param node the starting node
146- * @return the last node in the linked list
147- */
148- private Node <K , V > findEnd (Node <K , V > node ) {
149- while (node .getNext () != null ) {
150- node = node .getNext ();
151- }
152- return node ;
153- }
154-
155- /**
156- * Finds the node associated with the specified key in the linked list.
159+ * Finds the node associated with the specified key.
157160 *
158161 * @param key the key to search for
159162 * @return the node associated with the specified key, or null if not found
160163 */
161- public Node <K , V > findKey (K key ) {
164+ private Node <K , V > findNode (K key ) {
162165 Node <K , V > temp = head ;
163166 while (temp != null ) {
167+ // Robust key comparison, handles null keys correctly
164168 if ((key == null && temp .getKey () == null ) || (temp .getKey () != null && temp .getKey ().equals (key ))) {
165169 return temp ;
166170 }
@@ -169,32 +173,46 @@ public Node<K, V> findKey(K key) {
169173 return null ;
170174 }
171175
176+ /**
177+ * Finds the value associated with the specified key.
178+ *
179+ * @param key the key to search for
180+ * @return the value associated with the specified key, or null if not found
181+ */
182+ public V findValue (K key ) {
183+ Node <K , V > node = findNode (key );
184+ return node != null ? node .getValue () : null ;
185+ }
186+
187+
172188 /**
173189 * Deletes the node associated with the specified key from the linked list.
174- * Handles the case where the key could be null.
175190 *
176191 * @param key the key whose associated node is to be deleted
192+ * @return true if the node was successfully deleted, false otherwise.
177193 */
178- public void delete (K key ) {
194+ public boolean delete (K key ) {
179195 if (isEmpty ()) {
180- return ;
196+ return false ;
181197 }
182198
183- // Handle the case where the head node has the key to delete
199+ // Handle head deletion
184200 if ((key == null && head .getKey () == null ) || (head .getKey () != null && head .getKey ().equals (key ))) {
185201 head = head .getNext ();
186- return ;
202+ return true ;
187203 }
188204
189- // Traverse the list to find and delete the node
205+ // Traverse to find node to delete
190206 Node <K , V > current = head ;
191207 while (current .getNext () != null ) {
192- if ((key == null && current .getNext ().getKey () == null ) || (current .getNext ().getKey () != null && current .getNext ().getKey ().equals (key ))) {
193- current .setNext (current .getNext ().getNext ());
194- return ;
208+ Node <K , V > nextNode = current .getNext ();
209+ if ((key == null && nextNode .getKey () == null ) || (nextNode .getKey () != null && nextNode .getKey ().equals (key ))) {
210+ current .setNext (nextNode .getNext ());
211+ return true ;
195212 }
196213 current = current .getNext ();
197214 }
215+ return false ; // Key not found
198216 }
199217
200218 /**
@@ -203,25 +221,16 @@ public void delete(K key) {
203221 * @return a string representation of the linked list
204222 */
205223 public String display () {
206- return display (head );
207- }
208-
209- /**
210- * Constructs a string representation of the linked list non-recursively.
211- *
212- * @param node the starting node
213- * @return a string representation of the linked list starting from the given node
214- */
215- private String display (Node <K , V > node ) {
216224 StringBuilder sb = new StringBuilder ();
225+ Node <K , V > node = head ;
217226 while (node != null ) {
218227 sb .append (node .getKey ()).append ("=" ).append (node .getValue ());
219228 node = node .getNext ();
220229 if (node != null ) {
221230 sb .append (" -> " );
222231 }
223232 }
224- return sb .toString (). isEmpty () ? "null" : sb .toString ();
233+ return sb .length () > 0 ? sb .toString () : "empty" ;
225234 }
226235
227236 /**
@@ -234,64 +243,37 @@ public boolean isEmpty() {
234243 }
235244 }
236245
246+ // --- NESTED NODE CLASS (Key-Value Pair) ---
247+
237248 /**
238- * A nested static class representing a node in the linked list.
239- *
240- * @param <K> the type of key maintained by this node
241- * @param <V> the type of value maintained by this node
249+ * A nested static class representing a node (Entry) in the linked list.
242250 */
243251 public static class Node <K , V > {
244252 private final K key ;
245253 private V value ;
246254 private Node <K , V > next ;
247255
248- /**
249- * Constructs a Node with the specified key and value.
250- *
251- * @param key the key associated with this node
252- * @param value the value associated with this node
253- */
254256 public Node (K key , V value ) {
255257 this .key = key ;
256258 this .value = value ;
257259 }
258260
259- /**
260- * Gets the key associated with this node.
261- *
262- * @return the key associated with this node
263- */
264261 public K getKey () {
265262 return key ;
266263 }
267264
268- /**
269- * Gets the value associated with this node.
270- *
271- * @return the value associated with this node
272- */
273265 public V getValue () {
274266 return value ;
275267 }
276268
277- public void setValue (V value ) { // This method allows updating the value
269+ public void setValue (V value ) {
278270 this .value = value ;
279271 }
280272
281- /**
282- * Gets the next node in the linked list.
283- *
284- * @return the next node in the linked list
285- */
286273 public Node <K , V > getNext () {
287274 return next ;
288275 }
289276
290- /**
291- * Sets the next node in the linked list.
292- *
293- * @param next the next node to be linked
294- */
295277 public void setNext (Node <K , V > next ) {
296278 this .next = next ;
297279 }
0 commit comments