JavaRush /Java Blog /Random-ID /Menghapus elemen dari ArrayList di Java

Menghapus elemen dari ArrayList di Java

Dipublikasikan di grup Random-ID
Halo! Pada kuliah terakhir, kita mengenal kelas ArrayList , dan juga mempelajari cara melakukan operasi paling umum dengannya. Selain itu, kami telah mengidentifikasi beberapa perbedaan antara ArrayList dan array biasa. Sekarang mari kita lihat menghapus elemen dari ArrayList. Kami telah mengatakan bahwa menghapus elemen dalam array biasa sangat tidak nyaman. Menghapus elemen dari ArrayList - 1Karena kita tidak bisa menghapus sel itu sendiri, kita hanya bisa “menghilangkan” 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("Hippopotamus");
       cats[2] = new Cat("Philip Markovich");

       cats[1] = null;

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


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Kesimpulan:

[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
Namun saat direset, “lubang” tetap ada di array. Kami tidak menghapus selnya, tetapi hanya isinya. Bayangkan apa yang akan terjadi jika kita memiliki 50 kucing, 17 di antaranya kita hapus dengan cara ini. Kami akan memiliki array dengan 17 lubang, dan menjaganya! Mengingat jumlah sel kosong tempat Anda dapat menulis nilai baru tidak realistis. Buat kesalahan sekali dan Anda akan menimpa sel dengan referensi objek yang diinginkan. Tentu saja ada peluang untuk melakukannya dengan lebih hati-hati: setelah menghapus, pindahkan elemen array ke awal, sehingga "lubang" berada di akhir:
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));
}
Kesimpulan:

[Cat{name='Томас'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}, null]
Sekarang tampaknya terlihat lebih baik, tapi ini hampir tidak bisa disebut solusi yang stabil. Minimal, karena kita harus menulis kode ini dengan tangan setiap kali kita menghapus elemen dari array! Pilihan yang buruk. Anda dapat melakukan cara lain dan membuat metode terpisah:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...remove the cat by index and shift the elements
}
Tapi ini juga tidak banyak gunanya: metode ini hanya bisa bekerja dengan objek Cat, tetapi tidak bisa bekerja dengan yang lain. Artinya, jika ada 100 kelas lagi dalam program yang ingin kita gunakan arraynya, kita harus menulis metode yang sama dengan logika yang persis sama di masing-masing kelas. Ini adalah kegagalan total -_- Tapi di kelas ArrayList masalah ini berhasil diselesaikan! Ini mengimplementasikan metode khusus untuk menghapus elemen - 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());
}
Kami meneruskan indeks objek kami ke metode tersebut, dan indeks tersebut telah dihapus (seperti dalam array). Metode ini remove()memiliki dua fitur. Pertama , tidak meninggalkan “lubang”. Ini sudah mengimplementasikan logika perpindahan elemen ketika menghapus elemen dari tengah, yang sebelumnya kita tulis dengan tangan. Lihatlah keluaran kode sebelumnya di konsol:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
Kami mengeluarkan satu kucing dari tengah dan yang lainnya dipindahkan sehingga tidak ada celah. Kedua , ia dapat menghapus suatu objek tidak hanya berdasarkan indeks (seperti array biasa), tetapi juga dengan referensi ke objek tersebut :
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());
}
Kesimpulan:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
Ini bisa sangat berguna jika Anda tidak ingin selalu mengingat indeks objek yang diinginkan. Kami tampaknya telah menyelesaikan penghapusan yang biasa. Sekarang mari kita bayangkan situasi ini: kita ingin mengulangi daftar elemen dan menghapus kucing dengan nama tertentu. Untuk ini kami menggunakan operator loop khusus for- for each. Anda dapat mempelajarinya lebih lanjut dalam kuliah ini .
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);
}
Kode tersebut tampaknya terlihat cukup logis. Namun, hasilnya mungkin mengejutkan Anda:

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)
Semacam kesalahan, dan tidak jelas kenapa tiba-tiba muncul. Ada sejumlah nuansa dalam proses ini yang perlu ditangani. Aturan umum yang perlu Anda ingat: Anda tidak dapat melakukan iterasi melalui koleksi dan mengubah elemennya secara bersamaan. Ya, ya, tepatnya perubahan, dan bukan sekadar penghapusan. Jika Anda mencoba kode kami untuk mengganti penghapusan kucing dengan memasukkan yang baru, hasilnya akan sama:
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)
Kami mengubah satu operasi ke operasi lainnya, tetapi hasilnya tidak berubah: kesalahan yang sama ConcurrentModificationException. Ini terjadi justru ketika kita mencoba melanggar aturan dan mengubah daftar sambil mengulanginya. Di Java, untuk menghapus elemen selama iterasi, Anda perlu menggunakan objek khusus - sebuah iterator (kelas Iterator). Kelas Iteratorbertanggung jawab untuk menelusuri daftar elemen dengan aman. Caranya cukup sederhana karena hanya memiliki 3 cara:
  • hasNext()- kembali truetergantung falsepada apakah ada elemen berikutnya dalam daftar, atau apakah kita telah mencapai elemen terakhir.
  • next()- mengembalikan elemen daftar berikutnya
  • remove()- menghapus elemen dari daftar
Seperti yang Anda lihat, iterator secara harfiah “disesuaikan” dengan kebutuhan kita, dan tidak ada yang rumit di dalamnya. Misalnya, kami ingin memeriksa apakah daftar kami berisi elemen berikut, dan jika demikian, cetaklah ke konsol:
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
}
Kesimpulan:

Cat{name='Томас'}
Cat{name='Бегемот'}
Cat{name='Фorпп Маркович'}
Cat{name='Пушок'}
Seperti yang Anda lihat, kelas ArrayListsudah mengimplementasikan metode khusus untuk membuat iterator - iterator(). Perhatikan juga bahwa saat membuat iterator, kami menentukan kelas objek yang akan digunakan ( <Cat>). Pada akhirnya, kita dapat dengan mudah menyelesaikan masalah awal kita menggunakan iterator. Sebagai contoh, mari kita hapus seekor kucing bernama “Philip Markovich”:
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);
Kesimpulan:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
Anda mungkin memperhatikan bahwa kami tidak menentukan indeks elemen atau nama variabel referensi dalam metode iterator remove()! Iterator lebih pintar dari yang terlihat: metode ini remove()menghapus elemen terakhir yang dikembalikan oleh iterator. Seperti yang Anda lihat, ini berfungsi persis seperti yang diperlukan :) Pada dasarnya itulah semua yang perlu Anda ketahui tentang menghapus elemen dari ArrayList. Lebih tepatnya, hampir semuanya. Pada kuliah berikutnya kita akan melihat “bagian dalam” kelas ini dan melihat apa yang terjadi di sana selama operasi :) Sampai jumpa!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION