CodeGym /Blog Java /rawak /Memadamkan elemen daripada ArrayList
John Squirrels
Tahap
San Francisco

Memadamkan elemen daripada ArrayList

Diterbitkan dalam kumpulan
Hai! Dalam pelajaran lepas, kami berkenalan dengan ArrayListkelas, dan belajar cara melaksanakan operasi yang paling biasa dengan kelas ini. Di samping itu, kami menunjukkan beberapa perbezaan antara tatasusunan ArrayListdan tatasusunan biasa. Tetapi kami mengetepikan satu topik, iaitu, cara memadam elemen daripada ArrayList. Kami akan membincangkannya sekarang. Memadamkan elemen daripada ArrayList - 1Kami telah menyebut bahawa memadamkan elemen daripada tatasusunan biasa tidak begitu mudah. Oleh kerana kita tidak boleh memadamkan elemen itu sendiri, kita hanya boleh "sifarkan" (ditetapkan kepada null) nilainya:

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 + '\'' +
               '}';
   }
}
Output: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] Tetapi menetapkan elemen tatasusunan kepada null meninggalkan "lubang". Kami belum mengalih keluar kedudukan dalam tatasusunan, hanya kandungannya. Bayangkan apa yang akan berlaku jika kita mempunyai susunan 50 kucing dan mengeluarkan 17 daripadanya dengan cara ini. Kami akan mempunyai tatasusunan dengan 17 lubang. Cuba menjejaki mereka! Adalah tidak realistik untuk mengharapkan untuk mengingati bilangan sel kosong yang boleh anda tulis nilai baharu. Jika anda membuat satu kesilapan, anda akan menulis ganti rujukan objek yang anda mahukan. Sudah tentu, terdapat cara untuk melakukan ini dengan lebih berhati-hati: selepas mengalih keluar elemen, gerakkan elemen ke hadapan tatasusunan untuk meletakkan "lubang" di hujung:

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));
}
Output: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='Fluffy'}, null] Ini nampaknya lebih baik, tetapi ia sukar dipanggil penyelesaian yang mantap. Jika tidak ada sebab lain daripada fakta bahawa kita perlu menulis kod ini setiap kali apabila kita memadamkan elemen daripada tatasusunan! Ini adalah pilihan yang tidak baik. Kita boleh pergi dengan cara lain dan mencipta kaedah berasingan:

public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
Tetapi ini juga tidak banyak digunakan: kaedah ini hanya boleh berfungsi dengan Catobjek, tetapi bukan jenis lain. Dalam erti kata lain, jika program mempunyai 100 kelas lagi yang kita mahu gunakan dengan tatasusunan, kita perlu menulis kaedah yang sama dengan logik yang sama dalam setiap satu daripadanya. Ini adalah bencana total -_- Tetapi ArrayListkelas menyelesaikan masalah ini! Ia melaksanakan kaedah khas untuk mengeluarkan unsur: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());
}
Kami menghantar indeks objek kami kepada kaedah, yang memadamkannya (sama seperti dalam tatasusunan). Kaedah ini remove()mempunyai dua ciri khas. Pertama, ia tidak meninggalkan "lubang". Ia sudah melaksanakan logik yang diperlukan untuk mengalihkan elemen apabila elemen dialih keluar dari tengah, yang sebelum ini kami tulis sendiri. Lihat output dari kod sebelumnya:

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

[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
Kami mengeluarkan satu kucing dari tengah, dan selebihnya dipindahkan supaya tidak ada ruang kosong. Kedua , ia boleh memadam objek bukan sahaja dengan indeks (seperti tatasusunan biasa), tetapi juga dengan rujukan :

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());
}
Output: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Ini boleh menjadi sangat mudah jika anda tidak mahu sentiasa menjejaki indeks objek yang diingini. Nampaknya kami telah mengetahui pemadaman biasa. Sekarang mari kita bayangkan situasi ini: kita ingin mengulangi senarai kami dan mengalih keluar kucing dengan nama tertentu . Untuk melakukan ini, kami akan menggunakan forgelung pantas (juga dipanggil gelung untuk setiap satu), yang kami telah diperkenalkan dalam pelajaran Rishi:

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);
}
Kod itu kelihatan sangat logik. Tetapi hasilnya mungkin satu kejutan besar: Pengecualian dalam utas "utama" java.util.ConcurrentModificationException di java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) di java.util.ArrayList$Itr.next(ArrayList. java:831) di Cat.main(Cat.java:25) Terdapat beberapa jenis ralat dan tidak jelas mengapa ia berlaku. Proses ini melibatkan beberapa nuansa yang mesti ditangani. Berikut ialah peraturan am yang perlu anda ingat: Anda tidak boleh mengulang koleksi dan menukar elemennya secara serentak. Dan kami maksudkan apa-apa jenis perubahan, bukan sekadar penyingkiran. Jika anda menggantikan penyingkiran kucing dengan percubaan untuk memasukkan kucing baharu, hasilnya akan sama:

for (Cat cat: cats) {

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

System.out.println(cats);
Pengecualian dalam benang "utama" java.util.ConcurrentModificationException di java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) di java.util.ArrayList$Itr.next(ArrayList.java:831) di Cat.main( Cat.java:25) Kami menukar satu operasi kepada yang lain, tetapi hasilnya tidak berubah: kami mendapat ConcurrentModificationException yang sama . Ia berlaku tepat apabila kita cuba melanggar peraturan di atas dengan menukar senarai sambil mengulanginya. Di Java, kita memerlukan objek khas yang dipanggil iterator (Iteratorkelas) untuk memadam item semasa melelaran pada koleksi. KelasIteratorbertanggungjawab untuk melakar senarai elemen dengan selamat. Ia agak mudah, kerana ia hanya mempunyai 3 kaedah:
  • hasNext()- mengembalikan benar atau salah, bergantung pada sama ada terdapat item seterusnya dalam senarai, atau kami telah mencapai yang terakhir.
  • next()- mengembalikan item seterusnya dalam senarai
  • remove()- mengalih keluar item daripada senarai
Seperti yang anda lihat, iterator dibuat khusus untuk keperluan kita, dan pada masa yang sama tiada apa-apa yang rumit mengenainya. Katakan kami ingin menyemak sama ada terdapat elemen seterusnya dalam senarai kami, dan memaparkannya jika terdapat:

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
}
Output: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} Seperti yang anda lihat, telah melaksanakan kaedah ArrayListkhas untuk mencipta lelaran: iterator(). Selain itu, ambil perhatian bahawa apabila kami mencipta iterator, kami menentukan kelas objek yang akan berfungsi dengannya ( <Cat>). Intinya adalah bahawa iterator mudah mengendalikan tugas asal kami. Contohnya, keluarkan kucing bernama "Lionel Messi":

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);
Output: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Anda mungkin perasan bahawa kami tidak menyatakan sama ada indeks atau nama dalam remove()kaedah iterator ! Peulang lebih bijak daripada yang mungkin muncul: remove()mengalih keluar elemen terakhir yang dikembalikan oleh peulang. Seperti yang anda lihat, ia melakukan apa yang kami mahukan :) Pada dasarnya, ini adalah semua yang anda perlu tahu tentang mengalih keluar elemen daripada ArrayList. Nah, hampir semuanya. Dalam pelajaran seterusnya, kita akan melihat di dalam kelas ini, dan melihat apa yang berlaku di sana semasa pelbagai panggilan kaedah :) Sehingga itu!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION