JavaRush /جاوا بلاگ /Random-SD /جاوا ۾ ArrayList مان هڪ عنصر کي هٽائڻ

جاوا ۾ ArrayList مان هڪ عنصر کي هٽائڻ

گروپ ۾ شايع ٿيل
سلام! پوئين ليڪچر ۾، اسان ArrayList طبقي سان واقف ٿياسين ، ۽ اهو پڻ سکيو ته ان سان سڀ کان عام آپريشن ڪيئن ڪجي. اضافي طور تي، اسان نمايان ڪئي آهي ڪافي فرقن جي وچ ۾ ArrayList ۽ هڪ باقاعده صف. ھاڻي اچو ته ArrayList مان ھڪڙي عنصر کي ختم ڪرڻ تي نظر رکون. اسان اڳ ۾ ئي چيو آهي ته عناصر کي باقاعده صف ۾ ختم ڪرڻ بلڪل آسان ناهي. ArrayList مان هڪ عنصر کي هٽائڻ - 1جيئن ته اسان سيل کي ختم نٿا ڪري سگھون، اسان صرف ان جي قيمت "صفر" ڪري سگھون ٿا:
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Hippopotamus");
       cats[2] = new Cat("Philip Markovich");

       cats[1] = null;

       System.out.println(Arrays.toString(cats));
   }


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
نتيجو:

[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
پر جڏهن ري سيٽ ڪيو ويو، هڪ "سوراخ" صف ۾ رهي ٿو. اسان سيل کي ختم نه ڪري رهيا آهيون، پر صرف ان جي مواد کي. تصور ڪريو ته ڇا ٿيندو جيڪڏهن اسان وٽ 50 ٻليون آهن، جن مان 17 کي اسان هن طريقي سان ڊاهي ڇڏيو. اسان وٽ 17 سوراخن سان گڏ ھڪڙو صف آھي، ۽ انھن جي سنڀال ڪريو! خالي خانن جي تعداد کي دل سان ياد ڪرڻ جتي توهان نوان قدر لکي سگهو ٿا غير حقيقي آهي. هڪ ڀيرو غلطي ڪريو ۽ توهان سيل کي اوور رائٽ ڪنداسين اعتراض جي گهربل حوالي سان. يقينن، ھڪڙو موقعو آھي اھو ڪجھھ وڌيڪ احتياط سان ڪرڻ لاء: ختم ڪرڻ کان پوء، صف جي عناصر کي شروعات ڏانھن منتقل ڪريو، جيئن ته "سوراخ" آخر ۾ آھي:
public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Hippopotamus");
   cats[2] = new Cat("Philip Markovich");
   cats[3] = new Cat("Fluff");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       //move the elements to the beginning so that the empty cell is at the end
       cats[i-1] = cats[i];
       cats[i] = null;
   }

   System.out.println(Arrays.toString(cats));
}
نتيجو:

[Cat{name='Томас'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}, null]
هاڻي اهو بهتر ڏسڻ ۾ اچي ٿو، پر اهو مشڪل سان هڪ مستحڪم حل چئي سگهجي ٿو. گھٽ ۾ گھٽ، ڇو ته اسان کي ھٿ سان ھي ڪوڊ لکڻو پوندو ھر وقت جڏھن اسين صف مان ڪو عنصر ڪڍون ٿا! خراب اختيار. توھان ٻئي طريقي سان وڃو ۽ ھڪڙو الڳ طريقو ٺاھيو:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...remove the cat by index and shift the elements
}
پر اهو پڻ ٿورو استعمال جو آهي: هي طريقو صرف شيون سان ڪم ڪري سگهي ٿو Cat، پر ٻين سان ڪم نٿو ڪري سگهي. يعني جيڪڏهن پروگرام ۾ 100 وڌيڪ ڪلاس آهن جن سان اسان arrays استعمال ڪرڻ چاهيون ٿا، ته اسان کي انهن مان هر هڪ ۾ بلڪل ساڳي منطق سان ساڳيو طريقو لکڻو پوندو. هي هڪ مڪمل ناڪامي آهي -_- پر ArrayList ڪلاس ۾ اهو مسئلو ڪاميابي سان حل ڪيو ويو آهي! اهو عناصر کي هٽائڻ لاء هڪ خاص طريقو لاڳو ڪري ٿو remove()-
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
اسان پنهنجي اعتراض جي انڊيڪس کي طريقي سان منظور ڪيو، ۽ اهو ختم ٿي ويو (جهڙوڪ هڪ صف ۾). طريقو remove()ٻه خاصيتون آهن. پهرين ، اهو نه ڇڏيندو آهي "سوراخ". اهو اڳ ۾ ئي عنصرن کي تبديل ڪرڻ جي منطق کي لاڳو ڪري ٿو جڏهن وچين مان هڪ عنصر کي هٽايو، جيڪو اسان اڳ ۾ هٿ سان لکيو هو. ڪنسول ۾ پوئين ڪوڊ جي آئوٽ کي ڏسو:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
اسان ھڪڙي ٻلي کي وچ مان ڪڍي ڇڏيو ۽ ٻين کي چوڌاري منتقل ڪيو ويو ته جيئن ڪو خال نه ھو. ٻيو ، اهو هڪ اعتراض کي ختم ڪري سگهي ٿو نه رڳو انڊيڪس (جهڙوڪ هڪ باقاعده صف)، پر اعتراض جي حوالي سان پڻ :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);
   System.out.println(cats.toString());

   cats.remove(philipp);

   System.out.println(cats.toString());
}
نتيجو:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
اهو تمام آسان ٿي سگهي ٿو جيڪڏهن توهان نٿا چاهيو ته توهان هميشه پنهنجي سر ۾ گهربل اعتراض جي انڊيڪس کي برقرار رکون ٿا. لڳي ٿو ته اسان معمول کي ختم ڪري ڇڏيو آهي. هاڻي اچو ته هن صورتحال کي تصور ڪريون: اسان عناصر جي فهرست ذريعي ٻيهر ورجائڻ چاهيون ٿا ۽ هڪ خاص نالي سان ٻلي کي هٽائڻ چاهيون ٿا. هن لاء اسان هڪ خاص لوپ آپريٽر استعمال ڪندا آهيون for- for each. توھان ان بابت وڌيڪ سکي سگھوٿا ھن ليڪچر ۾ .
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   for (Cat cat: cats) {

       if (cat.name.equals("Hippopotamus")) {
           cats.remove(cat);
       }
   }

   System.out.println(cats);
}
ڪوڊ ڪافي منطقي نظر اچي ٿو. بهرحال، نتيجو توهان کي حيران ڪري سگهي ٿو:

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  at java.util.ArrayList$Itr.next(ArrayList.java:831)
  at Cat.main(Cat.java:25)
ڪجهه قسم جي غلطي، ۽ اهو واضح ناهي ته اهو اوچتو ڇو ظاهر ٿيو. ھن عمل ۾ ڪيتريون ئي nuances آھن جن سان معاملو ڪرڻ جي ضرورت آھي. هڪ عام قاعدو جيڪو توهان کي ياد رکڻ جي ضرورت آهي: توهان هڪ جمع ذريعي ٻيهر نه ٿا سگهو ۽ ساڳئي وقت ان جي عناصر کي تبديل ڪري سگهو ٿا. ها، ها، بلڪل هڪ تبديلي، ۽ نه صرف هڪ حذف. جيڪڏهن توهان اسان جي ڪوڊ ۾ ڪوشش ڪريو ته ٻلين کي هٽائڻ کي تبديل ڪرڻ سان نوان داخل ڪرڻ سان، نتيجو ساڳيو ٿيندو:
for (Cat cat: cats) {

   cats.add(new Cat("Salem Saberhegen"));
}

System.out.println(cats);

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  at java.util.ArrayList$Itr.next(ArrayList.java:831)
  at Cat.main(Cat.java:25)
اسان هڪ آپريشن کي ٻئي ۾ تبديل ڪيو، پر نتيجو تبديل نه ڪيو: ساڳيو غلطي ConcurrentModificationException. اهو صحيح طور تي ٿئي ٿو جڏهن اسان هڪ قاعدي کي ٽوڙڻ جي ڪوشش ڪندا آهيون ۽ فهرست کي تبديل ڪرڻ دوران ان جي ذريعي ٻيهر ورجائيندا آهيون. جاوا ۾، ورهاڱي دوران عناصر کي هٽائڻ لاء، توهان کي هڪ خاص اعتراض استعمال ڪرڻ جي ضرورت آهي - هڪ آئٽرٽر (ڪلاس Iterator). ڪلاس Iteratorمحفوظ طور تي عناصر جي فهرست ذريعي هلڻ جو ذميوار آهي. اهو بلڪل سادو آهي ڇاڪاڻ ته ان ۾ صرف 3 طريقا آهن:
  • hasNext()- واپسي trueيا ته falseان تي منحصر آهي ته ڇا فهرست ۾ ايندڙ عنصر آهي، يا ڇا اسان اڳ ۾ ئي آخري پهچي چڪا آهيون.
  • next()- فهرست جي ايندڙ عنصر کي واپس ڏئي ٿو
  • remove()- فهرست مان هڪ عنصر هٽائي ٿو
جئين توهان ڏسي سگهو ٿا، ايٽرٽر لفظي طور تي اسان جي ضرورتن جي مطابق "ٺاهيل" آهي، ۽ ان بابت ڪا به پيچيده ناهي. مثال طور، اسان چيڪ ڪرڻ چاهيون ٿا ته اسان جي لسٽ ۾ هيٺ ڏنل عنصر شامل آهي، ۽ جيڪڏهن ائين آهي، ان کي پرنٽ ڪنسول ڏانهن:
Iterator<Cat> catIterator = cats.iterator();//create an iterator
while(catIterator.hasNext()) {//as long as there are elements in the list

   Cat nextCat = catIterator.next();//get next element
   System.out.println(nextCat);// print it to the console
}
نتيجو:

Cat{name='Томас'}
Cat{name='Бегемот'}
Cat{name='Фorпп Маркович'}
Cat{name='Пушок'}
جئين توھان ڏسي سگھو ٿا، ڪلاس ArrayListاڳ ۾ ئي ھڪڙو خاص طريقو لاڳو ڪري ٿو ھڪڙو ٺاھيندڙ ٺاھيندڙ - iterator(). اهو پڻ نوٽ ڪريو ته هڪ آئٽرٽر ٺاهڻ وقت، اسان شين جو ڪلاس بيان ڪندا آهيون جنهن سان اهو ڪم ڪندو ( <Cat>). آخرڪار، اسان آساني سان حل ڪري سگھون ٿا اسان جو اصل مسئلو هڪ آئٽرٽر استعمال ڪندي. مثال طور، اچو ته ”فلپ مارڪووچ“ نالي ٻلي کي ختم ڪريون:
Iterator<Cat> catIterator = cats.iterator();//create an iterator
while(catIterator.hasNext()) {//as long as there are elements in the list

   Cat nextCat = catIterator.next();//get next element
   if (nextCat.name.equals("Philip Markovich")) {
       catIterator.remove();//delete the cat with the desired name
   }
}

System.out.println(cats);
نتيجو:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
توھان شايد محسوس ڪيو ھوندو آھي ته اسان يا ته عنصر انڊيڪس يا حوالو متغير جو نالو بيان نه ڪيو آھي iterator طريقي ۾ remove()! آئٽرٽر وڌيڪ هوشيار آهي ان کان وڌيڪ لڳي سگھي ٿو: طريقو remove()آخري عنصر کي هٽائي ٿو جيڪو آئٽرٽر طرفان واپس آيو هو. جئين توهان ڏسي سگهو ٿا، اهو بلڪل ڪم ڪيو جيئن ضرورت هجي :) اهو بنيادي طور تي هر شيء آهي جيڪو توهان کي ڄاڻڻ جي ضرورت آهي مان عناصر کي هٽائڻ بابت ArrayList. وڌيڪ صحيح - لڳ ڀڳ سڀڪنھن شيء کي. ايندڙ ليڪچر ۾ اسين هن ڪلاس جي ”اندرون“ تي نظر وجهنداسين ۽ ڏسنداسين ته آپريشن دوران اتي ڇا ٿيندو آهي :) ملنداسين!
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION