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("Hello");
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);
}


for-each4. लूपमधील घटक काढून टाकणे

लूपमध्ये for-eachएक कमतरता आहे: ते घटक योग्यरित्या काढू शकत नाही. तुम्ही असा कोड लिहिल्यास, तुम्हाला एरर मिळेल.

कोड नोंद
ArrayList<String> list = new ArrayList<String>();

list.add("Hello");
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 collection, तुम्ही काउंटर व्हेरिएबलसह सामान्य लूप वापरू शकता i.

कोड
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.

घटक स्वतःच डुप्लिकेट केलेले नसल्यामुळे संग्रह त्वरीत कॉपी केला जातो. त्याऐवजी, नवीन संग्रह जुन्या संग्रहात आधीपासून अस्तित्वात असलेल्या घटकांचे संदर्भ संग्रहित करतो.