CodeGym /Java Blog /এলোমেলো /একটি ArrayList থেকে একটি উপাদান মুছে ফেলা হচ্ছে
John Squirrels
লেভেল 41
San Francisco

একটি 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("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

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

   
@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
আউটপুট: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] কিন্তু null করার জন্য একটি অ্যারে উপাদান সেট করা একটি "গর্ত" ছেড়ে দেয়। আমরা অ্যারের অবস্থানটি মুছে ফেলিনি, শুধুমাত্র এর বিষয়বস্তু। কল্পনা করুন যদি আমাদের কাছে 50টি বিড়ালের একটি অ্যারে থাকে এবং তাদের মধ্যে 17টি এভাবে সরিয়ে দেয় তাহলে কী হবে। আমাদের 17টি গর্ত সহ একটি অ্যারে থাকবে। শুধু তাদের ট্র্যাক রাখার চেষ্টা করুন! আপনি নতুন মান লিখতে পারেন এমন খালি ঘরের সংখ্যা মনে রাখার আশা করা অবাস্তব। আপনি যদি একটি ভুল করেন, আপনি চান এমন একটি বস্তুর রেফারেন্স ওভাররাইট করবেন। অবশ্যই, এটি আরও একটু সাবধানে করার একটি উপায় রয়েছে: একটি উপাদান অপসারণের পরে, উপাদানগুলিকে অ্যারের সামনে নিয়ে যান যাতে "গর্ত" শেষ হয়:

public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Behemoth");
   cats[2] = new Cat("Lionel Messi");
   cats[2] = new Cat("Fluffy");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       cats [i-1] = cats [i];// Move the elements to the front of the array, so the empty position is at the end
   }

   System.out.println(Arrays.toString(cats));
}
আউটপুট: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='fluffy'}, null] এটি আরও ভাল বলে মনে হয়, তবে এটিকে খুব কমই একটি শক্তিশালী সমাধান বলা যেতে পারে। অন্য কোন কারণে যদি আমরা একটি অ্যারে থেকে একটি উপাদান মুছে ফেলার সময় প্রতিবার এই কোড লিখতে হবে! এটি একটি খারাপ বিকল্প। আমরা অন্য উপায়ে যেতে পারি এবং একটি পৃথক পদ্ধতি তৈরি করতে পারি:

public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
কিন্তু এটিও সামান্য কাজে লাগে: এই পদ্ধতিটি শুধুমাত্র বস্তুর সাথে কাজ করতে পারে Cat, কিন্তু অন্য ধরনের নয়। অন্য কথায়, যদি একটি প্রোগ্রামের আরও 100টি ক্লাস থাকে যা আমরা অ্যারেগুলির সাথে ব্যবহার করতে চাই, আমাদের তাদের প্রতিটিতে ঠিক একই যুক্তি দিয়ে একই পদ্ধতি লিখতে হবে। এটি একটি সম্পূর্ণ বিপর্যয় -_- কিন্তু ArrayListক্লাস এই সমস্যার সমাধান করে! এটি উপাদান অপসারণের জন্য একটি বিশেষ পদ্ধতি প্রয়োগ করে:remove()

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
আমরা আমাদের বস্তুর সূচীটি পদ্ধতিতে পাস করি, যা এটিকে মুছে দেয় (ঠিক একটি অ্যারের মতো)। পদ্ধতির remove()দুটি বিশেষ বৈশিষ্ট্য রয়েছে। প্রথমত, এটি "গর্ত" ছেড়ে যায় না। এটি ইতিমধ্যেই উপাদানগুলিকে স্থানান্তরের জন্য প্রয়োজনীয় যুক্তি প্রয়োগ করে যখন একটি উপাদান মাঝখান থেকে সরানো হয়, যা আমরা আগে নিজেরাই লিখেছিলাম। আগের কোড থেকে আউটপুট দেখুন:

[Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]

[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
আমরা মাঝখান থেকে একটি বিড়াল সরিয়েছি, এবং বাকিগুলি সরানো হয়েছিল যাতে কোনও খালি জায়গা না থাকে। দ্বিতীয়ত , এটি শুধুমাত্র সূচী দ্বারা নয় (একটি সাধারণ অ্যারের মত), কিন্তু রেফারেন্স দ্বারা বস্তু মুছে ফেলতে পারে :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(lionel);

   System.out.println(cats.toString());
}
আউটপুট: [বিড়াল{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] [Cat{name='Thomas'}, বিড়াল{name='Behemoth'}, Cat{name='Fluffy'}] আপনি যদি পছন্দসই বস্তুর সূচী সর্বদা ট্র্যাক রাখতে না চান তবে এটি খুব সুবিধাজনক হতে পারে। মনে হচ্ছে আমরা সাধারণ মুছে ফেলার চিন্তা করেছি। এখন এই পরিস্থিতিটি কল্পনা করা যাক: আমরা আমাদের তালিকার উপর পুনরাবৃত্তি করতে চাই এবং একটি নির্দিষ্ট নামের একটি বিড়াল সরাতে চাই । এটি করার জন্য, আমরা একটি দ্রুত লুপ ব্যবহার করব for(এটিকে প্রতিটি লুপের জন্যও বলা হয়), যা ঋষির পাঠে আমাদের পরিচয় করা হয়েছিল:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   for (Cat cat: cats) {

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

   System.out.println(cats);
}
কোড পুরোপুরি যৌক্তিক দেখায়. তবে ফলাফলটি একটি বড় আশ্চর্য হতে পারে: java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) এ java.util.ArrayList$Itr.next(ArrayList. java:831) Cat.main(Cat.java:25) এ এক ধরণের ত্রুটি রয়েছে এবং কেন এটি ঘটেছে তা স্পষ্ট নয়। এই প্রক্রিয়াটিতে বেশ কয়েকটি সূক্ষ্মতা রয়েছে যা অবশ্যই সমাধান করা উচিত। এখানে সাধারণ নিয়মটি আপনার মনে রাখা দরকার: আপনি একই সাথে একটি সংগ্রহের উপর পুনরাবৃত্তি করতে এবং এর উপাদানগুলি পরিবর্তন করতে পারবেন না। এবং আমরা যেকোন ধরণের পরিবর্তন বলতে চাই, নিছক অপসারণ নয়। আপনি যদি বিড়াল অপসারণের পরিবর্তে নতুন বিড়াল সন্নিবেশ করার চেষ্টা করেন, ফলাফল একই হবে:

for (Cat cat: cats) {

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

System.out.println(cats);
java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) এ java.util.ArrayList$Itr.next(ArrayList.java:831 এ) থ্রেড "প্রধান" java.util.ConcurrentModificationException এ ব্যতিক্রম Cat.java:25) আমরা একটি অপারেশন অন্যটিতে পরিবর্তন করেছি, কিন্তু ফলাফল পরিবর্তন হয়নি: আমরা একই ConcurrentModificationException পাই । এটি ঠিক তখনই ঘটে যখন আমরা তালিকাটি পুনরাবৃত্তি করার সময় পরিবর্তন করে উপরের নিয়মটি ভঙ্গ করার চেষ্টা করি। জাভাতে,একটি সংগ্রহের উপর পুনরাবৃত্তি করার সময় আইটেমগুলি মুছে ফেলার জন্য আমাদের একটি ইটারেটর (Iteratorক্লাসটিIteratorউপাদানগুলির তালিকার উপর নিরাপদে পুনরাবৃত্তি করার জন্য দায়ী। এটি বেশ সহজ, যেহেতু এটির মাত্র 3টি পদ্ধতি রয়েছে:
  • hasNext()- তালিকায় পরবর্তী আইটেম আছে কিনা বা আমরা ইতিমধ্যেই শেষটিতে পৌঁছেছি তার উপর নির্ভর করে সত্য বা মিথ্যা ফেরত দেয়।
  • 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 the next element
   System.out.println(nextCat);// Display it
}
আউটপুট: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} আপনি দেখতে পাচ্ছেন, এটি তৈরি করার জন্য ইতিমধ্যে একটি 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 the next element
   if (nextCat.name.equals("Lionel Messi")) {
       catIterator.remove();// Delete the cat with the specified name
   }
}

System.out.println(cats);
আউটপুট: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] আপনি হয়তো লক্ষ্য করেছেন যে আমরা পুনরাবৃত্তিকারীর পদ্ধতিতে সূচী বা নাম উল্লেখ remove()করিনি ! পুনরাবৃত্তিকারী এটি প্রদর্শিত হতে পারে তার চেয়ে স্মার্ট: remove()পুনরাবৃত্তিকারী দ্বারা ফিরে আসা শেষ উপাদানটি সরিয়ে দেয়। আপনি দেখতে পাচ্ছেন, এটি ঠিক তাই করেছে যা আমরা এটি করতে চেয়েছিলাম :) নীতিগতভাবে, এটি একটি থেকে উপাদানগুলি সরানোর বিষয়ে আপনার যা জানা দরকার ArrayList। ভাল, প্রায় সবকিছু. পরবর্তী পাঠে, আমরা এই ক্লাসের ভিতরে দেখব, এবং বিভিন্ন পদ্ধতি কলের সময় সেখানে কী ঘটে তা দেখব :) ততক্ষণ পর্যন্ত!
মন্তব্য
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION