Biarkan saya memberi beberapa contoh dengan beberapa alternatif untuk menghindari a ConcurrentModificationException
.
Misalkan kita memiliki koleksi buku berikut
List<Book> books = new ArrayList<Book>();
books.add(new Book(new ISBN("0-201-63361-2")));
books.add(new Book(new ISBN("0-201-63361-3")));
books.add(new Book(new ISBN("0-201-63361-4")));
Kumpulkan dan Hapus
Teknik pertama terdiri dari mengumpulkan semua objek yang ingin kita hapus (mis. Menggunakan loop yang disempurnakan) dan setelah kita selesai iterasi, kita menghapus semua objek yang ditemukan.
ISBN isbn = new ISBN("0-201-63361-2");
List<Book> found = new ArrayList<Book>();
for(Book book : books){
if(book.getIsbn().equals(isbn)){
found.add(book);
}
}
books.removeAll(found);
Seandainya operasi yang ingin Anda lakukan adalah "hapus".
Jika Anda ingin "menambahkan" pendekatan ini juga akan berfungsi, tetapi saya akan menganggap Anda akan mengulangi koleksi yang berbeda untuk menentukan elemen apa yang ingin Anda tambahkan ke koleksi kedua dan kemudian mengeluarkan addAll
metode di akhir.
Menggunakan ListIterator
Jika Anda bekerja dengan daftar, teknik lain terdiri dari penggunaan ListIterator
yang memiliki dukungan untuk penghapusan dan penambahan item selama iterasi itu sendiri.
ListIterator<Book> iter = books.listIterator();
while(iter.hasNext()){
if(iter.next().getIsbn().equals(isbn)){
iter.remove();
}
}
Sekali lagi, saya menggunakan metode "hapus" dalam contoh di atas yang tampaknya menyiratkan pertanyaan Anda, tetapi Anda juga dapat menggunakan add
metode ini untuk menambahkan elemen baru selama iterasi.
Menggunakan JDK> = 8
Bagi mereka yang bekerja dengan Java 8 atau versi superior, ada beberapa teknik lain yang bisa Anda gunakan untuk memanfaatkannya.
Anda bisa menggunakan removeIf
metode baru di Collection
kelas dasar:
ISBN other = new ISBN("0-201-63361-2");
books.removeIf(b -> b.getIsbn().equals(other));
Atau gunakan API aliran baru:
ISBN other = new ISBN("0-201-63361-2");
List<Book> filtered = books.stream()
.filter(b -> b.getIsbn().equals(other))
.collect(Collectors.toList());
Dalam kasus terakhir ini, untuk memfilter elemen dari koleksi, Anda menetapkan kembali referensi asli ke koleksi yang difilter (yaitu books = filtered
) atau menggunakan koleksi yang difilter ke removeAll
elemen yang ditemukan dari koleksi asli (yaitu books.removeAll(filtered)
).
Gunakan Sublist atau Subset
Ada alternatif lain juga. Jika daftar diurutkan, dan Anda ingin menghapus elemen berturut-turut Anda dapat membuat sublist dan kemudian menghapusnya:
books.subList(0,5).clear();
Karena sublist didukung oleh daftar asli, ini akan menjadi cara yang efisien untuk menghilangkan subkoleksi elemen ini.
Hal serupa dapat dicapai dengan set yang diurutkan menggunakan NavigableSet.subSet
metode, atau metode pemotongan apa pun yang ditawarkan di sana.
Pertimbangan:
Metode apa yang Anda gunakan mungkin tergantung pada apa yang ingin Anda lakukan
- Koleksi dan
removeAl
teknik bekerja dengan Koleksi apa pun (Koleksi, Daftar, Set, dll.).
- The
ListIterator
Teknik jelas hanya bekerja dengan daftar, asalkan diberikan mereka ListIterator
menawarkan implementasi dukungan untuk add dan menghapus operasi.
- The
Iterator
pendekatan akan bekerja dengan semua jenis koleksi, tetapi hanya mendukung operasi menghapus.
- Dengan pendekatan
ListIterator
/ Iterator
keuntungan yang jelas adalah tidak perlu menyalin apa pun karena kita menghapus seperti yang kita lakukan berulang kali. Jadi, ini sangat efisien.
- Contoh JDK 8 stream sebenarnya tidak menghapus apa pun, tetapi mencari elemen yang diinginkan, dan kemudian kami mengganti referensi koleksi asli dengan yang baru, dan membiarkan yang lama menjadi sampah yang dikumpulkan. Jadi, kami hanya mengulang koleksi sekali saja dan itu akan efisien.
- Dalam mengumpulkan dan
removeAll
mendekati kerugiannya adalah kita harus mengulang dua kali. Pertama kita mengulang di loop foor mencari objek yang cocok dengan kriteria penghapusan kami, dan setelah kami menemukannya, kami meminta untuk menghapusnya dari koleksi asli, yang akan menyiratkan pekerjaan iterasi kedua untuk mencari item ini untuk Singkirkan.
- Saya pikir perlu disebutkan bahwa metode hapus
Iterator
antarmuka ditandai sebagai "opsional" di Javadocs, yang berarti bahwa mungkin ada Iterator
implementasi yang melempar UnsupportedOperationException
jika kita memanggil metode hapus. Karena itu, saya akan mengatakan pendekatan ini kurang aman dibandingkan yang lain jika kami tidak dapat menjamin dukungan iterator untuk menghilangkan elemen.