1. இட்ரேட்டர்கள் எப்படி வந்தன என்பதன் பின்னணி

உங்களுக்கு ஏற்கனவே தெரிந்திருக்கும் HashSet. ஒரு பாடத்தைப் படிப்பதைத் தாண்டி நீங்கள் உண்மையிலேயே அதை ஆராய்ந்திருந்தால், நீங்கள் இந்தக் கேள்வியைக் கேட்டிருக்க வேண்டும்:

திரையில் உள்ள அனைத்து 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.

கூறுகள் நகலெடுக்கப்படாததால் சேகரிப்பு விரைவாக நகலெடுக்கப்படுகிறது. அதற்கு பதிலாக, புதிய சேகரிப்பு பழைய சேகரிப்பில் ஏற்கனவே உள்ள கூறுகளின் குறிப்புகளை சேமிக்கிறது.