1. इटरेटर कैसे बने इसकी पृष्ठभूमि

आप पहले से ही परिचित हैं HashSet। यदि आपने वास्तव में इसकी जांच की है, सिर्फ एक पाठ पढ़ने से परे, तो आपको यह प्रश्न पूछना चाहिए था:

मैं स्क्रीन पर सभी हैशसेट तत्वों की सूची कैसे प्रदर्शित करूं? आखिरकार, इंटरफ़ेस में get()और set()तरीके नहीं हैं!

और HashSetइस सीमा में अकेला नहीं है। इसके अलावा HashSet, कई अन्य संग्रह हैं जो तत्वों को अनुक्रमणिका द्वारा पुनर्प्राप्त करने की अनुमति नहीं देते हैं, क्योंकि तत्वों का कोई परिभाषित क्रम नहीं है।

पिछले कुछ वर्षों में, प्रोग्रामर ने कई जटिल डेटा संरचनाओं का आविष्कार किया है, जैसे ग्राफ और पेड़। या सूचियों की सूची।

जब नए तत्व जोड़े जाते हैं या मौजूदा तत्वों को हटा दिया जाता है, तो कई कंटेनर अपने तत्वों का क्रम बदल देते हैं। उदाहरण के लिए, एक सूची तत्वों को एक विशेष क्रम में संग्रहीत करती है, और जब कोई नया तत्व जोड़ा जाता है, तो यह लगभग हमेशा सूची के बीच में डाला जाता है।

और हमें ऐसी परिस्थितियाँ भी मिलती हैं जहाँ एक कंटेनर होता है जो तत्वों को संग्रहीत करता है लेकिन किसी निश्चित क्रम में नहीं।

अब मान लीजिए कि हम ऐसे संग्रह से सभी तत्वों को एक सरणी या सूची में कॉपी करना चाहते हैं। हमें सभी तत्वों को प्राप्त करने की आवश्यकता है। हम उस क्रम के बारे में परवाह नहीं करते हैं जिसमें हम तत्वों पर पुनरावृति करते हैं - महत्वपूर्ण बात यह है कि समान तत्वों पर एक से अधिक बार पुनरावृति न करें। हम इसे कैसे करते हैं?


2. संग्रह के लिए इटरेटर

उपरोक्त समस्या के समाधान के रूप में इटरेटर प्रस्तावित किए गए थे।

एक पुनरावर्तक एक संग्रह से जुड़ी एक विशेष वस्तु है, जो बिना किसी को दोहराए संग्रह के सभी तत्वों को पार करने में मदद करता है।

आप किसी संग्रह के लिए पुनरावर्तक प्राप्त करने के लिए निम्न कोड का उपयोग कर सकते हैं:

Iterator<Type> it = name.iterator();

जहां nameसंग्रह चर का नाम है, Typeसंग्रह के तत्वों का प्रकार है, iterator()संग्रह के तरीकों में से एक है, और itपुनरावर्तक चर का नाम है।

एक पुनरावर्तक वस्तु में 3 विधियाँ होती हैं:

तरीका विवरण
Type next()
संग्रह में अगला तत्व लौटाता है
boolean hasNext()
जाँचता है कि क्या कोई तत्व है जो अभी तक ट्रैवर्स नहीं किया गया है
void remove()
संग्रह के वर्तमान तत्व को हटाता है

ये विधियाँ कुछ हद तक स्कैनर वर्ग nextInt)और hasNextInt()विधियों के समान हैं।

विधि next()उस संग्रह का अगला तत्व लौटाती है जिससे हमें पुनरावृत्त मिला।

विधि hasNext()जाँचती है कि क्या संग्रह में अतिरिक्त तत्व हैं जो कि पुनरावर्तक अभी तक वापस नहीं आया है।

यहां ए के सभी तत्वों को प्रदर्शित करने का तरीका बताया गया है HashSet:

कोड टिप्पणियाँ
HashSet<String> set = new HashSet<String>();

set.add("Hallo");
set.add("Hello");
set.add("Hola");
set.add("Bonjour");
set.add("Ciao");
set.add("Namaste");

Iterator<String> it = set.iterator();
while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}
HashSetएक वस्तु बनाएँ जो Stringतत्वों को संग्रहीत करती है। हम चर


में विभिन्न भाषाओं में अभिवादन जोड़ते हैं । सेट के लिए एक पुनरावर्तक वस्तु प्राप्त करें । जब तक तत्व हैं अगला तत्व प्राप्त करें स्क्रीन पर तत्व प्रदर्शित करें set




set





3. For-eachपाश

पुनरावर्तक का मुख्य नुकसान यह है कि forलूप का उपयोग करने से आपका कोड अधिक बोझिल हो जाता है।

forतुलना करने के लिए, एक लूप का उपयोग करके और एक पुनरावर्तक का उपयोग करके एक सूची प्रदर्शित करें :

इटरेटर पाश के लिए
ArrayList<String> list = new ArrayList<String>();

Iterator<String> it = list.iterator();
while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();

for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);
   System.out.println(str);
}

ArrayListहां, लूप का उपयोग करके तत्वों को पार करना बहुत बेहतर है - सब कुछ छोटा हो जाता है।

लेकिन जावा के रचनाकारों ने फिर से हम पर कुछ चीनी डालने का फैसला किया। सौभाग्य से हमारे लिए, यह सिंटैक्टिक चीनी थी ।

उन्होंने जावा को एक नए प्रकार का लूप दिया और उसे for-eachलूप कहा। यह सामान्य रूप में कैसा दिखता है:

for(Type name:collection)

collectionसंग्रह चर का नाम कहाँ है, Typeसंग्रह में तत्वों का प्रकार है, और nameएक चर का नाम है जो लूप के प्रत्येक पुनरावृत्ति पर संग्रह से अगला मान लेता है।

इस प्रकार का लूप एक निहित पुनरावर्तक का उपयोग करके संग्रह के सभी तत्वों के माध्यम से पुनरावृत्त करता है। यह वास्तव में कैसे काम करता है:

प्रत्येक पाश के लिए संकलक क्या देखता है: एक पुनरावर्तक के साथ लूप
ArrayList<String> list = new ArrayList<String>();

for (String str: list)
{
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();
Iterator<String> it = list.iterator();

while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}

जब कंपाइलर for-eachआपके कोड में एक लूप का सामना करता है, तो यह बस इसे दाईं ओर के कोड से बदल देता है: यह किसी अन्य लापता विधि कॉल के साथ एक पुनरावर्तक प्राप्त करने के लिए कॉल जोड़ता है।

प्रोग्रामर for-eachलूप को पसंद करते हैं और लगभग हमेशा इसका उपयोग तब करते हैं जब उन्हें किसी संग्रह के सभी तत्वों पर पुनरावृति करने की आवश्यकता होती है।

ArrayListलूप का उपयोग करके किसी सूची पर पुनरावृति करना भी for-eachछोटा दिखता है:

प्रत्येक पाश के लिए पाश के लिए
ArrayList<String> list = new ArrayList<String>();

for (String str: list)
{
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();

for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);
   System.out.println(str);
}


4. एक for-eachपाश में एक तत्व को हटाना

लूप for-eachमें एक खामी है: यह तत्वों को सही ढंग से नहीं निकाल सकता है। यदि आप इस तरह का कोड लिखते हैं, तो आपको एक त्रुटि मिलेगी।

कोड टिप्पणी
ArrayList<String> list = new ArrayList<String>();

list.add("Hallo");
list.add("Hello");
list.add("Hola");
list.add("Bonjour");
list.add("Ciao");
list.add("Namaste");

for (String str: list)
{
   if (str.equals("Hello"))
      list.remove(str);
}












हटाने की कार्रवाई एक त्रुटि उत्पन्न करेगी!

यह एक बहुत अच्छा और समझने योग्य कोड है, लेकिन यह काम नहीं करेगा।

महत्वपूर्ण!

जब आप इसे पुनरावर्तक के साथ घुमा रहे हों तो आप संग्रह को बदल नहीं सकते हैं।

इस सीमा के आसपास जाने के तीन तरीके हैं।

1. एक अलग तरह के लूप का इस्तेमाल करें

When traversing an ArrayList collectioni, आप एक काउंटर चर के साथ एक साधारण पाश का उपयोग कर सकते हैं ।

कोड
for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);

   if (str.equals("Hello"))
   {
      list.remove(str);
      i--; // We need to decrease i, because the remove operation shifted the elements
   }
}

HashSetहालांकि, यह विकल्प और HashMapसंग्रह के लिए उपयुक्त नहीं है

2. एक स्पष्ट पुनरावर्तक का प्रयोग करें

आप एक पुनरावर्तक का स्पष्ट रूप से उपयोग कर सकते हैं और इसकी remove()विधि को कॉल कर सकते हैं।

संस्करण जो काम करता है संस्करण जो काम नहीं करता
Iterator<String> it = set.iterator();
while (it.hasNext())
{
   String str = it.next();
   if (str.equals("Hello"))
       it.remove();
}

for (String str: list) { if (str.equals("Hello")) list.remove(str); }

ध्यान दें कि हम remove()इटेटरेटर ऑब्जेक्ट पर विधि कहते हैं! इटरेटर जानता है कि आइटम हटा दिया गया है और स्थिति को सही ढंग से संभाल सकता है।

3. संग्रह की एक प्रति का उपयोग करें

आप संग्रह की प्रतिलिपि भी बना सकते हैं और फिर प्रतिलिपि का उपयोग for-eachलूप में कर सकते हैं और मूल संग्रह से तत्वों को हटा सकते हैं।

कोड टिप्पणी
ArrayList<String> listCopy = new ArrayList(list);

for (String str: listCopy)
{
   if (str.equals("Hello"))
      list.remove(str);
}
संग्रह की प्रतिलिपि बनाना बेहद आसान है



लूप संग्रह की प्रति के लिए पुनरावर्तक का उपयोग करता है। संग्रह
से तत्वों को हटा दिया जाता है ।list

संग्रह को जल्दी से कॉपी किया जाता है, क्योंकि तत्व स्वयं डुप्लिकेट नहीं होते हैं। इसके बजाय, नया संग्रह उन तत्वों के संदर्भों को संग्रहीत करता है जो पुराने संग्रह में पहले से मौजूद हैं।