From b8a502399e43da9d122e728041ceca3723786f27 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Thu, 24 Oct 2024 11:23:14 +0530 Subject: [PATCH 1/3] refactor: Enhance docs, add tests in `GenericHashMapUsingArray` --- .../hashing/GenericHashMapUsingArray.java | 116 +++++++++++++++--- .../hashing/GenericHashMapUsingArrayTest.java | 43 +++++++ 2 files changed, 139 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java index 416cee99d028..5a05d8273f6b 100644 --- a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java +++ b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java @@ -2,23 +2,46 @@ import java.util.LinkedList; -// implementation of generic hashmaps using array of Linked Lists - +/** + * A generic implementation of a hash map using an array of linked lists for collision resolution. + * This class provides a way to store key-value pairs efficiently, allowing for average-case + * constant time complexity for insertion, deletion, and retrieval operations. + * + *

+ * The hash map uses separate chaining for collision resolution. Each bucket in the hash map is a + * linked list that stores nodes containing key-value pairs. When a collision occurs (i.e., when + * two keys hash to the same index), the new key-value pair is simply added to the corresponding + * linked list. + *

+ * + *

+ * The hash map automatically resizes itself when the load factor exceeds 0.75. The load factor is + * defined as the ratio of the number of entries to the number of buckets. When resizing occurs, + * all existing entries are rehashed and inserted into the new buckets. + *

+ * + * @param the type of keys maintained by this hash map + * @param the type of mapped values + */ public class GenericHashMapUsingArray { - private int size; // n (total number of key-value pairs) - private LinkedList[] buckets; // N = buckets.length - private float lf = 0.75f; + private int size; // Total number of key-value pairs + private LinkedList[] buckets; // Array of linked lists (buckets) for storing entries + private final float loadFactorThreshold = 0.75f; // Load factor threshold for resizing + /** + * Constructs a new empty hash map with an initial capacity of 16. + */ public GenericHashMapUsingArray() { initBuckets(16); size = 0; } - // load factor = 0.75 means if we need to add 100 items and we have added - // 75, then adding 76th item it will double the size, copy all elements - // & then add 76th item. - + /** + * Initializes the buckets for the hash map with the specified number of buckets. + * + * @param n the number of buckets to initialize + */ private void initBuckets(int n) { buckets = new LinkedList[n]; for (int i = 0; i < buckets.length; i++) { @@ -26,43 +49,65 @@ private void initBuckets(int n) { } } + /** + * Associates the specified value with the specified key in this map. + * If the map previously contained a mapping for the key, the old value is replaced. + * + * @param key the key with which the specified value is to be associated + * @param value the value to be associated with the specified key + */ public void put(K key, V value) { int bucketIndex = hashFunction(key); LinkedList nodes = buckets[bucketIndex]; - for (Node node : nodes) { // if key present => update + // Update existing key's value if present + for (Node node : nodes) { if (node.key.equals(key)) { node.value = value; return; } } - // key is not present => insert + // Insert new key-value pair nodes.add(new Node(key, value)); size++; - if ((float) size / buckets.length > lf) { + // Check if rehashing is needed + if ((float) size / buckets.length > loadFactorThreshold) { reHash(); } } - // tells which bucket to go to + /** + * Returns the index of the bucket in which the key would be stored. + * + * @param key the key whose bucket index is to be computed + * @return the bucket index + */ private int hashFunction(K key) { return Math.floorMod(key.hashCode(), buckets.length); } + /** + * Rehashes the map by doubling the number of buckets and re-inserting all entries. + */ private void reHash() { System.out.println("Rehashing!"); - LinkedList[] old = buckets; - initBuckets(old.length * 2); + LinkedList[] oldBuckets = buckets; + initBuckets(oldBuckets.length * 2); this.size = 0; - for (LinkedList nodes : old) { + for (LinkedList nodes : oldBuckets) { for (Node node : nodes) { put(node.key, node.value); } } } + /** + * Removes the mapping for the specified key from this map if present. + * + * @param key the key whose mapping is to be removed from the map + */ public void remove(K key) { int bucketIndex = hashFunction(key); LinkedList nodes = buckets[bucketIndex]; @@ -74,14 +119,28 @@ public void remove(K key) { break; } } - nodes.remove(target); - size--; + + if (target != null) { + nodes.remove(target); + size--; + } } + /** + * Returns the number of key-value pairs in this map. + * + * @return the number of key-value pairs + */ public int size() { return this.size; } + /** + * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. + * + * @param key the key whose associated value is to be returned + * @return the value associated with the specified key, or null if no mapping exists + */ public V get(K key) { int bucketIndex = hashFunction(key); LinkedList nodes = buckets[bucketIndex]; @@ -96,7 +155,6 @@ public V get(K key) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("{"); for (LinkedList nodes : buckets) { for (Node node : nodes) { @@ -106,19 +164,37 @@ public String toString() { builder.append(", "); } } + // Remove trailing comma and space + if (builder.length() > 1) { + builder.setLength(builder.length() - 2); + } builder.append("}"); return builder.toString(); } + /** + * Returns true if this map contains a mapping for the specified key. + * + * @param key the key whose presence in this map is to be tested + * @return true if this map contains a mapping for the specified key + */ public boolean containsKey(K key) { return get(key) != null; } + /** + * A private class representing a key-value pair (node) in the hash map. + */ public class Node { - K key; V value; + /** + * Constructs a new Node with the specified key and value. + * + * @param key the key of the key-value pair + * @param value the value of the key-value pair + */ public Node(K key, V value) { this.key = key; this.value = value; diff --git a/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java index 483e43bb5cb3..5d1733a3e97c 100644 --- a/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java +++ b/src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayTest.java @@ -50,4 +50,47 @@ void testGenericHashmapWhichUsesArrayAndKeyIsIntegerValueIsString() { assertEquals("Washington DC", map.get(101)); assertTrue(map.containsKey(46)); } + + @Test + void testRemoveNonExistentKey() { + GenericHashMapUsingArray map = new GenericHashMapUsingArray<>(); + map.put("USA", "Washington DC"); + map.remove("Nepal"); // Attempting to remove a non-existent key + assertEquals(1, map.size()); // Size should remain the same + } + + @Test + void testRehashing() { + GenericHashMapUsingArray map = new GenericHashMapUsingArray<>(); + for (int i = 0; i < 20; i++) { + map.put("Key" + i, "Value" + i); + } + assertEquals(20, map.size()); // Ensure all items were added + assertEquals("Value5", map.get("Key5")); // Check retrieval after rehash + } + + @Test + void testUpdateValueForExistingKey() { + GenericHashMapUsingArray map = new GenericHashMapUsingArray<>(); + map.put("USA", "Washington DC"); + map.put("USA", "New Washington DC"); // Updating value for existing key + assertEquals("New Washington DC", map.get("USA")); + } + + @Test + void testToStringMethod() { + GenericHashMapUsingArray map = new GenericHashMapUsingArray<>(); + map.put("USA", "Washington DC"); + map.put("Nepal", "Kathmandu"); + String expected = "{USA : Washington DC, Nepal : Kathmandu}"; + assertEquals(expected, map.toString()); + } + + @Test + void testContainsKey() { + GenericHashMapUsingArray map = new GenericHashMapUsingArray<>(); + map.put("USA", "Washington DC"); + assertTrue(map.containsKey("USA")); + assertFalse(map.containsKey("Nepal")); + } } From 00b0301312457bf0c3563c8925cbb3250a79c247 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Thu, 24 Oct 2024 11:29:49 +0530 Subject: [PATCH 2/3] Fix --- .../hashmap/hashing/GenericHashMapUsingArray.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java index 5a05d8273f6b..ed89dacd5ffa 100644 --- a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java +++ b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java @@ -27,7 +27,6 @@ public class GenericHashMapUsingArray { private int size; // Total number of key-value pairs private LinkedList[] buckets; // Array of linked lists (buckets) for storing entries - private final float loadFactorThreshold = 0.75f; // Load factor threshold for resizing /** * Constructs a new empty hash map with an initial capacity of 16. @@ -72,6 +71,8 @@ public void put(K key, V value) { size++; // Check if rehashing is needed + // Load factor threshold for resizing + float loadFactorThreshold = 0.75f; if ((float) size / buckets.length > loadFactorThreshold) { reHash(); } From 57a26e64ffa737ee8beb981943bd3001eaba16b7 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Tue, 29 Oct 2024 10:04:06 +0530 Subject: [PATCH 3/3] Fix --- .../datastructures/hashmap/hashing/GenericHashMapUsingArray.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java index ed89dacd5ffa..3637e323f097 100644 --- a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java +++ b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArray.java @@ -92,7 +92,6 @@ private int hashFunction(K key) { * Rehashes the map by doubling the number of buckets and re-inserting all entries. */ private void reHash() { - System.out.println("Rehashing!"); LinkedList[] oldBuckets = buckets; initBuckets(oldBuckets.length * 2); this.size = 0; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy