Skip to content

Commit 850981a

Browse files
committed
feat(HashMapCustom): add lightweight custom HashMap implementation with iterable support
What - Added HashMapCustom<K,V> core implementation with: - Entry<K,V> inner class (key, value, toString). - Basic operations: put(K,V), get(K), remove(K), size(), printMap(). - Automatic resizing with rehash when load factor threshold exceeded. - Configurable initial capacity and load factor (constructors + setLoadFactor()). - Iterable support: implements Iterable<Entry<K,V>> with an internal iterator that walks buckets in order. Why - Provide an educational, minimal reimplementation of a hash-based map to illustrate: - Hashing → bucket index calculation using hashCode and modulo. - Collision handling via separate chaining (LinkedList per bucket). - Rehashing/resizing strategy when load factor is exceeded. - How iteration across buckets and linked lists can be implemented. - Useful for teaching, debugging, or comparing behavior with java.util.HashMap in a controlled, transparent way. How - Buckets are an array of LinkedList<Entry<K,V>>. - getBucketIndex(key) computes Math.abs(key.hashCode()) % buckets.length. - put: - Locate bucket, create list if null. - If key exists, update value. - Else add new Entry and increment size. - After insert, check load factor and call resize() if needed. - get: - Locate bucket and scan entries, returning matching value or null. - remove: - Locate bucket, remove matching entry and decrement size. - resize: - Double bucket array length, rehash all existing entries by calling put() on each (size reset and recalculated). - printMap: - Iterate bucket array and print entries per bucket. - Iterable: - Custom HashMapIterator advances to next non-empty bucket and iterates its linked list; hasNext() peeks ahead to future buckets. Logic - Inputs: keys/values provided to put/get/remove. - Outputs: stored values retrievable by get, printed bucket layout via printMap. - Flow: 1. Compute bucket index from key. 2. Use separate chaining (LinkedList) to store entries for that index. 3. Maintain size and trigger resize when (double)size / buckets.length > loadFactor. 4. Iterator moves bucket-by-bucket and iterates each non-empty LinkedList. - Edge cases handled: - Null buckets lazily created. - Key equality uses entry.key.equals(key). - Resize rehashes entries into newly sized bucket array. - Iterator throws NoSuchElementException when exhausted. - Complexity: - Average put/get/remove are O(1) amortized; resize is O(n). - Iterator traverses all buckets and entries O(n). - Concurrency / thread-safety: - Implementation is not thread-safe; concurrent modifications may break behavior. - Error handling: - setLoadFactor rejects non-positive values with IllegalArgumentException. Real-life applications - Educational playground for students learning how hash maps work internally. - Small-scale custom mapping needs where controlling hashing/rehash behavior or instrumentation is required. - Basis for experiments: alternative collision strategies, probing, custom hashing, or instrumentation for teaching. Notes - Uses LinkedList chaining for simplicity; production HashMap uses optimized treeification for large buckets. - Buckets array created with raw type LinkedList[]; generics-aware creation is avoided for clarity but may be improved using @SuppressWarnings or Lists of lists. - Using Math.abs(key.hashCode()) may still be negative in one edge case (Integer.MIN_VALUE); consider handling that to avoid negative indices. - Rehashing uses put() which increments size; resize resets size to 0 before re-inserting to recalculate correctly. - The iterator implementation advances to next non-empty bucket lazily; it is fail-fast behavior is not implemented (no modCount). Signed-off-by: https://github.com/Someshdiwan <someshdiwan369@gmail.com>
1 parent 382a0a7 commit 850981a

1 file changed

Lines changed: 11 additions & 53 deletions

File tree

  • Section 25 Collections Frameworks/Map Interface/HashMap/Custom HashMap/src/CustomHashMap

Section25CollectionFramework/src/CustomHashMapDemo/HashMapCustom.java renamed to Section 25 Collections Frameworks/Map Interface/HashMap/Custom HashMap/src/CustomHashMap/HashMapCustom.java

Lines changed: 11 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
package CustomHashMapDemo;
2-
3-
/*
4-
extended version of the custom HashMap that includes:
5-
6-
- Iteration: Implements the Iterable interface so you can loop over all entries.
7-
- Dynamic Size Tracking: A method (`size()`) returns the current number of key-value pairs.
8-
- Load Factor Tuning: A configurable load factor (with getters and setters) and a constructor that accepts an initial capacity and load factor.
9-
10-
Extended Custom HashMap Implementation
11-
*/
1+
package CustomHashMap;
122

133
import java.util.Iterator;
144
import java.util.LinkedList;
155
import java.util.NoSuchElementException;
166

7+
/*
8+
Extended Custom HashMap Implementation (core class).
9+
This file contains the HashMapCustom<K, V> implementation with:
10+
- Entry inner class
11+
- put/get/remove/resize/printMap
12+
- Iterable support via an inner iterator class
13+
No main() in this file — main() moved to HashMapCustomTest.java
14+
*/
15+
1716
public class HashMapCustom<K, V> implements Iterable<HashMapCustom.Entry<K, V>> {
1817
private static final int DEFAULT_INITIAL_CAPACITY = 4;
1918
private static final double DEFAULT_LOAD_FACTOR = 0.75;
@@ -97,7 +96,7 @@ public void put(K key, V value) {
9796
}
9897
}
9998

100-
// Add new entry.
99+
// Add a new entry.
101100
buckets[index].add(new Entry<>(key, value));
102101
size++;
103102

@@ -213,45 +212,4 @@ public Entry<K, V> next() {
213212
return listIterator.next();
214213
}
215214
}
216-
217-
// Main method to test the extended CustomHashMap.
218-
public static void main(String[] args) {
219-
HashMapCustom<Object, Integer> map = new HashMapCustom<Object, Integer>();
220-
map.put("Alice", 25);
221-
map.put("Bob", 30);
222-
map.put("Charlie", 35);
223-
map.put("Alice", 28); // Update value for "Alice"
224-
225-
System.out.println("Value of Alice: " + map.get("Alice")); // 28
226-
System.out.println("Value of Bob: " + map.get("Bob")); // 30
227-
System.out.println("Value of Charlie: " + map.get("Charlie"));// 35
228-
229-
map.remove("Bob");
230-
System.out.println("Value of Bob after removal: " + map.get("Bob")); // null
231-
232-
System.out.println("\nCustom HashMap Contents:");
233-
map.printMap();
234-
235-
System.out.println("\nIterating over CustomHashMap entries:");
236-
for (HashMapCustom.Entry<Object, Integer> entry : map) {
237-
System.out.println(entry.getKey() + " -> " + entry.getValue());
238-
}
239-
}
240215
}
241-
/*
242-
Explanation of Extensions:
243-
244-
- Iteration:
245-
246-
- The class now implements Iterable<Entry<K, V>> and provides an inner HashMapIterator that traverses each non-empty bucket
247-
248-
- You can use a for-each loop to iterate over all key-value pairs.
249-
250-
- Dynamic Size Tracking:
251-
- The size field is updated on every put() and remove() call.
252-
- The size() method returns the current count of entries.
253-
254-
- Load Factor Tuning:
255-
- The loadFactor field is configurable through constructors and the setLoadFactor() method.
256-
- The resize() method uses this load factor to determine when to double the bucket array.
257-
*/

0 commit comments

Comments
 (0)