Java में HashMap: ट्रैवर्सल के दौरान 5 घातक गलतियाँ और उनसे कैसे बचें

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

परिचय: HashMap — दोस्त या दुश्मन?

\n\n

हर Java डेवलपर को देर-सबेर HashMap का सामना करना पड़ता है। यह शायद Java में Map इंटरफ़ेस का सबसे लोकप्रिय कार्यान्वयन है। लेकिन यहाँ एक विरोधाभास है: हर कोई जानता है कि मैप में एलिमेंट कैसे डाला जाए, लेकिन जब उसे ट्रैवर्स (इटरेट) करने की बात आती है, तो असली अफरा-तफरी शुरू हो जाती है। Stack Overflow पर "Iterate through a HashMap" प्रश्न ने हज़ारों बार देखा गया है, और वास्तविक प्रोजेक्ट्स में गलतियों की संख्या बहुत अधिक है।

\n\n

इस लेख में हम Java में HashMap को ट्रैवर्स करते समय होने वाली 5 सबसे खतरनाक गलतियों पर चर्चा करेंगे, जो एप्लिकेशन को क्रैश कर सकती हैं, डेटा हानि का कारण बन सकती हैं और कोड को अपठनीय बना सकती हैं। आप न केवल यह जानेंगे कि गलत तरीका क्या है, बल्कि प्रत्येक मामले के लिए कार्यशील पैटर्न भी प्राप्त करेंगे। चलिए शुरू करते हैं!

\n\n

गलती #1: ConcurrentModificationException — "चलते-चलते हटाना"

\n\n

समस्या क्या है?

\n

सबसे क्लासिक गलती। आप HashMap पर इटरेट कर रहे हैं और map.remove(key) के माध्यम से एक एलिमेंट को हटाने का प्रयास कर रहे हैं। 90% मामलों में, इसके परिणामस्वरूप ConcurrentModificationException होता है।

\n\n
// ❌ खतरनाक: यह अपवाद फेंकेगा!\nHashMap<String, Integer> scores = new HashMap<>();\nscores.put("Alice", 90);\nscores.put("Bob", 50);\nscores.put("Charlie", 70);\n\nfor (String name : scores.keySet()) {\n    if (scores.get(name) < 60) {\n        scores.remove(name); // ConcurrentModificationException!\n    }\n}\n
\n\n

ऐसा क्यों होता है?

\n

HashMap का आंतरिक इटरेटर एक संशोधन काउंटर (modCount) रखता है। जब आप सीधे कलेक्शन के माध्यम से कोई एलिमेंट हटाते हैं, तो काउंटर बदल जाता है, लेकिन इटरेटर को इसके बारे में पता नहीं चलता। अगले इटरेशन पर, यह जाँच करता है: "अरे, काउंटर मेल नहीं खा रहा! अपवाद फेंको।"

\n\n

इसे कैसे ठीक करें?

\n

अपनी remove() विधि के साथ Iterator का उपयोग करें:

\n\n
// ✅ सही: Iterator का उपयोग करें\nHashMap<String, Integer> scores = new HashMap<>();\nscores.put("Alice", 90);\nscores.put("Bob", 50);\nscores.put("Charlie", 70);\n\nIterator<Map.Entry<String, Integer>> iterator = scores.entrySet().iterator();\nwhile (iterator.hasNext()) {\n    Map.Entry<String, Integer> entry = iterator.next();\n    if (entry.getValue() < 60) {\n        iterator.remove(); // सुरक्षित निष्कासन!\n    }\n}\n
\n\n

Java 8 के साथ एक और भी सुंदर तरीका आया — removeIf():

\n\n
// ✅ और भी बेहतर: removeIf (Java 8+)\nscores.entrySet().removeIf(entry -> entry.getValue() < 60);\n
\n\n

गलती #2: keySet() और get() के माध्यम से धीमा ट्रैवर्सल

\n\n

समस्या क्या है?

\n

कई नौसिखिए ऐसा करते हैं:

\n\n
// ❌ धीमा: keySet() + get() — दोहरी खोज\nfor (String key : map.keySet()) {\n    System.out.println("Key: " + key + ", Value: " + map.get(key));\n}\n
\n\n

पहली नज़र में यह काम करता है। लेकिन समस्या यह है कि map.get(key) आंतरिक रूप से फिर से हैश खोजता है और बकेट को पार करता है। लूप के प्रत्येक चक्कर में, आप HashMap पर दो कॉल कर रहे हैं, एक के बजाय। छोटे मैप के लिए यह ध्यान देने योग्य नहीं है, लेकिन सैकड़ों हज़ारों एंट्रीज़ के लिए, यह 30-40% तक प्रदर्शन हानि है।

\n\n

इसे कैसे ठीक करें?

\n

हमेशा entrySet() का उपयोग करें — यह एक ही पास में "कुंजी-मान" जोड़े लौटाता है:

\n\n
// ✅ तेज़: entrySet() — एक ही पास\nfor (Map.Entry<String, Integer> entry : map.entrySet()) {\n    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());\n}\n
\n\n

या Java 8 के साथ forEach का उपयोग करें:

\n\n
// ✅ संक्षिप्त: forEach (Java 8+)\nmap.forEach((key, value) -> {\n    System.out.println("Key: " + key + ", Value: " + value);\n});\n
\n\n

गलती #3: एलिमेंट के क्रम में भ्रम

\n\n

समस्या क्या है?

\n

आपने कोड लिखा है जो HashMap को ट्रैवर्स करता है, और आप उम्मीद करते हैं कि एलिमेंट उसी क्रम में होंगे जिसमें वे डाले गए थे। लेकिन आपको पूरी तरह से अलग अनुक्रम मिलता है। इससे बग होते हैं, जो

ब्लॉग

पुस्तक अनुशंसाएँ