परिचय: Java में for-each लूप "किंग" क्यों बना?
\n\nअगर आपने Java में कम से कम एक हफ्ता कोडिंग की है, तो आपने for (Type var : collection) यह सिंटैक्स जरूर देखा होगा। इस संक्षिप्त सिंटैक्स को for-each लूप (या enhanced for loop) कहा जाता है। यह Java 5 (2004) में आया था और जल्दी ही डेवलपर्स का पसंदीदा बन गया।
लेकिन क्या आप जानते हैं कि जब JVM इस सिंटैक्स को देखता है तो अंदर क्या होता है? for-each, arrays के लिए सामान्य for लूप से धीमा क्यों हो सकता है? और यह कभी-कभी ConcurrentModificationException क्यों फेंकता है, भले ही आप कुछ डिलीट नहीं कर रहे हों?
इस लेख में हम Java में for-each लूप कैसे काम करता है, इसे बाइट-कोड स्तर पर समझेंगे, क्लासिकल लूप्स से तुलना करेंगे, और आम गलतियों से बचना सीखेंगे। चलिए शुरू करते हैं!
\n\nसिंटैक्स और पहली मुलाकात
\n\nबेसिक सिंटैक्स इस प्रकार है:
\n\nfor (एलिमेंट_टाइप वेरिएबल : कलेक्शन_या_ऐरे) {\n // लूप का बॉडी\n}\n\nArrayList के साथ उदाहरण:
List<String> names = Arrays.asList("अन्ना", "बोरिस", "विक्टर");\n\nfor (String name : names) {\n System.out.println("नमस्ते, " + name + "!");\n}\n\nआउटपुट:
\n\nनमस्ते, अन्ना!\nनमस्ते, बोरिस!\nनमस्ते, विक्टर!\n\nसरल है, है ना? लेकिन इस सादगी के पीछे दो पूरी तरह से अलग तंत्र छिपे हैं — एक arrays के लिए और दूसरा collections के लिए।
\n\nfor-each arrays के साथ कैसे काम करता है?
\n\nजब आप array के लिए for-each लिखते हैं, तो Java कंपाइलर इसे इंडेक्स वाले सामान्य for लूप में बदल देता है। कोई जादू नहीं।
आपका कोड:
\n\nint[] numbers = {10, 20, 30};\n\nfor (int num : numbers) {\n System.out.println(num);\n}\n\nकंपाइलेशन के बाद (बाइट-कोड डीकंपाइल करके देखें):
\n\nint[] numbers = new int[]{10, 20, 30};\nfor (int i = 0; i < numbers.length; i++) {\n int num = numbers[i];\n System.out.println(num);\n}\n\nमहत्वपूर्ण निष्कर्ष: arrays के लिए, for-each और सामान्य for लूप प्रदर्शन में एक समान हैं। इटरेटर का कोई अतिरिक्त खर्च नहीं है।
\n\nfor-each collections (List, Set) के साथ कैसे काम करता है?
\n\nयहाँ असली मजा शुरू होता है। Collections के लिए for-each इटरेटर का उपयोग करता है।
\n\nआपका कोड:
\n\nList<String> list = new ArrayList<>();\nlist.add("Java");\nlist.add("Python");\nlist.add("C++");\n\nfor (String lang : list) {\n System.out.println(lang);\n}\n\nकंपाइलर इसे इस प्रकार बदलता है:
\n\nList<String> list = new ArrayList<>();\nlist.add("Java");\nlist.add("Python");\nlist.add("C++");\n\nfor (Iterator<String> it = list.iterator(); it.hasNext(); ) {\n String lang = it.next();\n System.out.println(lang);\n}\n\nअर्थात:
\n- \n
list.iterator()कॉल होता है — इटरेटर प्राप्त होता है। \n - कंडीशन में —
it.hasNext()। \n - बॉडी में —
it.next()। \n - वेरिएबल
langकोnext()के रिजल्ट से इनिशियलाइज़ किया जाता है। \n
व्यवहार में इसका क्या मतलब है?
\n- \n
- for-each के अंदर एलिमेंट डिलीट नहीं कर सकते
list.remove()के माध्यम से — आपकोConcurrentModificationExceptionमिलेगा। इसके बजायit.remove()या सामान्य for लूप का उपयोग करें। \n - इटरेशन के दौरान कलेक्शन को बदल नहीं सकते (जोड़ना/हटाना) — वही एरर आएगी। \n
- प्रदर्शन:
ArrayListके लिए, सामान्य for लूप से अंतर न्यूनतम है (सिर्फ इटरेटर ऑब्जेक्ट बनाने का खर्च)।LinkedListके लिए — for-each बहुत तेज़ हैfor (int i = 0; i < list.size(); i++)की तुलना में, क्योंकि LinkedList मेंget(i)हर बार O(n) होता है! \n
Map के बारे में क्या? की-वैल्यू पेयर्स पर इटरेशन
\n\nMap सीधे Iterable को इम्प्लीमेंट नहीं करता, इसलिए for-each