Skip to content

Commit bc6ea1e

Browse files
authored
Enhance docs, fix & add tests in `GenericHashMapUsingArrayL… (TheAlgorithms#5973)
1 parent f5bc2c8 commit bc6ea1e

File tree

2 files changed

+128
-10
lines changed

2 files changed

+128
-10
lines changed

src/main/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayList.java

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,34 @@
33
import java.util.ArrayList;
44
import java.util.LinkedList;
55

6+
/**
7+
* A generic implementation of a hash map using an array list of linked lists for collision resolution.
8+
* This class allows storage of key-value pairs with average-case constant time complexity for insertion,
9+
* deletion, and retrieval operations.
10+
*
11+
* <p>
12+
* The hash map uses separate chaining to handle collisions. Each bucket in the hash map is represented
13+
* by a linked list that holds nodes containing key-value pairs. When multiple keys hash to the same index,
14+
* they are stored in the same linked list.
15+
* </p>
16+
*
17+
* <p>
18+
* The hash map automatically resizes itself when the load factor exceeds 0.5. The load factor is defined
19+
* as the ratio of the number of entries to the number of buckets. When resizing occurs, all existing entries
20+
* 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+
*/
626
public class GenericHashMapUsingArrayList<K, V> {
727

8-
ArrayList<LinkedList<Node>> buckets;
9-
private float lf = 0.5f;
10-
private int size;
28+
private ArrayList<LinkedList<Node>> buckets; // Array list of buckets (linked lists)
29+
private int size; // Number of key-value pairs in the hash map
1130

31+
/**
32+
* Constructs a new empty hash map with an initial capacity of 10 buckets.
33+
*/
1234
public GenericHashMapUsingArrayList() {
1335
buckets = new ArrayList<>();
1436
for (int i = 0; i < 10; i++) {
@@ -17,6 +39,13 @@ public GenericHashMapUsingArrayList() {
1739
size = 0;
1840
}
1941

42+
/**
43+
* Associates the specified value with the specified key in this map.
44+
* If the map previously contained a mapping for the key, the old value is replaced.
45+
*
46+
* @param key the key with which the specified value is to be associated
47+
* @param value the value to be associated with the specified key
48+
*/
2049
public void put(K key, V value) {
2150
int hash = Math.abs(key.hashCode() % buckets.size());
2251
LinkedList<Node> nodes = buckets.get(hash);
@@ -31,25 +60,36 @@ public void put(K key, V value) {
3160
nodes.add(new Node(key, value));
3261
size++;
3362

34-
if ((float) size / buckets.size() > lf) {
63+
// Load factor threshold for resizing
64+
float loadFactorThreshold = 0.5f;
65+
if ((float) size / buckets.size() > loadFactorThreshold) {
3566
reHash();
3667
}
3768
}
3869

70+
/**
71+
* Resizes the hash map by doubling the number of buckets and rehashing existing entries.
72+
*/
3973
private void reHash() {
40-
ArrayList<LinkedList<Node>> old = buckets;
74+
ArrayList<LinkedList<Node>> oldBuckets = buckets;
4175
buckets = new ArrayList<>();
4276
size = 0;
43-
for (int i = 0; i < old.size() * 2; i++) {
77+
for (int i = 0; i < oldBuckets.size() * 2; i++) {
4478
buckets.add(new LinkedList<>());
4579
}
46-
for (LinkedList<Node> nodes : buckets) {
80+
for (LinkedList<Node> nodes : oldBuckets) {
4781
for (Node node : nodes) {
4882
put(node.key, node.val);
4983
}
5084
}
5185
}
5286

87+
/**
88+
* Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
89+
*
90+
* @param key the key whose associated value is to be returned
91+
* @return the value associated with the specified key, or null if no mapping exists
92+
*/
5393
public V get(K key) {
5494
int hash = Math.abs(key.hashCode() % buckets.size());
5595
LinkedList<Node> nodes = buckets.get(hash);
@@ -61,6 +101,11 @@ public V get(K key) {
61101
return null;
62102
}
63103

104+
/**
105+
* Removes the mapping for the specified key from this map if present.
106+
*
107+
* @param key the key whose mapping is to be removed from the map
108+
*/
64109
public void remove(K key) {
65110
int hash = Math.abs(key.hashCode() % buckets.size());
66111
LinkedList<Node> nodes = buckets.get(hash);
@@ -72,18 +117,36 @@ public void remove(K key) {
72117
break;
73118
}
74119
}
75-
nodes.remove(target);
76-
size--;
120+
if (target != null) {
121+
nodes.remove(target);
122+
size--;
123+
}
77124
}
78125

126+
/**
127+
* Returns true if this map contains a mapping for the specified key.
128+
*
129+
* @param key the key whose presence in this map is to be tested
130+
* @return true if this map contains a mapping for the specified key
131+
*/
79132
public boolean containsKey(K key) {
80133
return get(key) != null;
81134
}
82135

136+
/**
137+
* Returns the number of key-value pairs in this map.
138+
*
139+
* @return the number of key-value pairs
140+
*/
83141
public int size() {
84142
return this.size;
85143
}
86144

145+
/**
146+
* Returns a string representation of the map, containing all key-value pairs.
147+
*
148+
* @return a string representation of the map
149+
*/
87150
@Override
88151
public String toString() {
89152
StringBuilder builder = new StringBuilder();
@@ -96,15 +159,27 @@ public String toString() {
96159
builder.append(", ");
97160
}
98161
}
162+
// Remove trailing comma and space if there are any elements
163+
if (builder.length() > 1) {
164+
builder.setLength(builder.length() - 2);
165+
}
99166
builder.append("}");
100167
return builder.toString();
101168
}
102169

170+
/**
171+
* A private inner class representing a key-value pair (node) in the hash map.
172+
*/
103173
private class Node {
104-
105174
K key;
106175
V val;
107176

177+
/**
178+
* Constructs a new Node with the specified key and value.
179+
*
180+
* @param key the key of the key-value pair
181+
* @param val the value of the key-value pair
182+
*/
108183
Node(K key, V val) {
109184
this.key = key;
110185
this.val = val;

src/test/java/com/thealgorithms/datastructures/hashmap/hashing/GenericHashMapUsingArrayListTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,47 @@ void testGenericHashmapWhichUsesArrayAndKeyIsIntegerValueIsString() {
5050
assertEquals("Washington DC", map.get(101));
5151
assertTrue(map.containsKey(46));
5252
}
53+
54+
@Test
55+
void testRemoveNonExistentKey() {
56+
GenericHashMapUsingArrayList<String, String> map = new GenericHashMapUsingArrayList<>();
57+
map.put("USA", "Washington DC");
58+
map.remove("Nepal"); // Attempting to remove a non-existent key
59+
assertEquals(1, map.size()); // Size should remain the same
60+
}
61+
62+
@Test
63+
void testRehashing() {
64+
GenericHashMapUsingArrayList<String, String> map = new GenericHashMapUsingArrayList<>();
65+
for (int i = 0; i < 20; i++) {
66+
map.put("Key" + i, "Value" + i);
67+
}
68+
assertEquals(20, map.size()); // Ensure all items were added
69+
assertEquals("Value5", map.get("Key5")); // Check retrieval after rehash
70+
}
71+
72+
@Test
73+
void testUpdateValueForExistingKey() {
74+
GenericHashMapUsingArrayList<String, String> map = new GenericHashMapUsingArrayList<>();
75+
map.put("USA", "Washington DC");
76+
map.put("USA", "New Washington DC"); // Updating value for existing key
77+
assertEquals("New Washington DC", map.get("USA"));
78+
}
79+
80+
@Test
81+
void testToStringMethod() {
82+
GenericHashMapUsingArrayList<String, String> map = new GenericHashMapUsingArrayList<>();
83+
map.put("USA", "Washington DC");
84+
map.put("Nepal", "Kathmandu");
85+
String expected = "{USA : Washington DC, Nepal : Kathmandu}";
86+
assertEquals(expected, map.toString());
87+
}
88+
89+
@Test
90+
void testContainsKey() {
91+
GenericHashMapUsingArrayList<String, String> map = new GenericHashMapUsingArrayList<>();
92+
map.put("USA", "Washington DC");
93+
assertTrue(map.containsKey("USA"));
94+
assertFalse(map.containsKey("Nepal"));
95+
}
5396
}

0 commit comments

Comments
 (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