JavaRush /جاوا بلاگ /Random-UR /جاوا میں 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='Пушок'}]
ہم نے ایک بلی کو درمیان سے ہٹا دیا اور باقی کو ادھر ادھر کر دیا گیا تاکہ کوئی خلا نہ رہے۔ دوم ، یہ کسی چیز کو نہ صرف index (جیسے ایک باقاعدہ صف) کے ذریعے حذف کر سکتا ہے، بلکہ آبجیکٹ کے حوالے سے بھی ۔
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)
کسی قسم کی خرابی، اور یہ واضح نہیں ہے کہ یہ اچانک کیوں ظاہر ہوا۔ اس عمل میں متعدد باریکیاں ہیں جن سے نمٹنے کی ضرورت ہے۔ ایک عام اصول جو آپ کو یاد رکھنے کی ضرورت ہے: آپ ایک مجموعہ کے ذریعے اعادہ نہیں کر سکتے اور ایک ہی وقت میں اس کے عناصر کو تبدیل نہیں کر سکتے۔ ہاں، ہاں، بالکل ایک تبدیلی، اور نہ صرف حذف کرنا۔ اگر آپ ہمارے کوڈ میں بلیوں کو ہٹانے کی جگہ نئی کو ڈالنے کی کوشش کرتے ہیں، تو نتیجہ وہی ہوگا:
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۔ یہ عین اس وقت ہوتا ہے جب ہم کسی اصول کو توڑنے کی کوشش کرتے ہیں اور اس کے ذریعے تکرار کرتے ہوئے فہرست کو تبدیل کرتے ہیں۔ جاوا میں، تکرار کے دوران عناصر کو ہٹانے کے لیے، آپ کو ایک خاص آبجیکٹ - ایک تکرار کرنے والا (class 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='Пушок'}]
آپ نے محسوس کیا ہوگا کہ ہم نے ایٹریٹر طریقہ میں عنصر انڈیکس یا حوالہ متغیر کا نام نہیں بتایا remove()! تکرار کرنے والا اس سے زیادہ ہوشیار ہے جیسا کہ لگتا ہے: طریقہ remove()آخری عنصر کو ہٹاتا ہے جو تکرار کرنے والے کے ذریعہ واپس کیا گیا تھا۔ جیسا کہ آپ دیکھ سکتے ہیں، اس نے بالکل ضرورت کے مطابق کام کیا :) بنیادی طور پر یہ وہ سب کچھ ہے جو آپ کو عناصر سے ہٹانے کے بارے میں جاننے کی ضرورت ہے ArrayList۔ زیادہ واضح طور پر - تقریبا ہر چیز۔ اگلے لیکچر میں ہم اس کلاس کے "اندرونی" کا جائزہ لیں گے اور دیکھیں گے کہ آپریشن کے دوران وہاں کیا ہوتا ہے :) ملتے ہیں!
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION