Bir kaçınmak için bazı alternatiflerle birkaç örnek vereyim ConcurrentModificationException
.
Aşağıdaki kitap koleksiyonuna sahip olduğumuzu varsayalım
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")));
Topla ve Kaldır
İlk teknik, silmek istediğimiz tüm nesneleri (örn. Döngü için gelişmiş bir kullanarak) toplamaktır ve yinelemeyi bitirdikten sonra bulunan tüm nesneleri kaldırırız.
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);
Bu, yapmak istediğiniz işlemin "sil" olduğunu varsayar.
"Eklemek" istiyorsanız bu yaklaşım da işe yarayacaktır, ancak ikinci bir koleksiyona hangi öğeleri eklemek istediğinizi belirlemek için farklı bir koleksiyon üzerinde yineleme yapacağınızı addAll
ve sonunda bir yöntem yayınlayacağınızı varsayarım .
ListIterator'ı kullanma
Listelerle çalışıyorsanız, başka bir teknik ListIterator
, yinelemenin kendisi sırasında öğelerin kaldırılması ve eklenmesi için destek olan bir yöntemi kullanmaktan oluşur .
ListIterator<Book> iter = books.listIterator();
while(iter.hasNext()){
if(iter.next().getIsbn().equals(isbn)){
iter.remove();
}
}
Yine, yukarıdaki örnekte sorunuzun ima ettiği gibi görünen "kaldır" yöntemini kullandım, ancak add
yöntemini yineleme sırasında yeni öğeler eklemek için de kullanabilirsiniz .
JDK kullanma> = 8
Java 8 veya üstün sürümlerle çalışanlar için, bundan yararlanmak için kullanabileceğiniz birkaç teknik daha vardır.
Temel sınıftaki yeni removeIf
yöntemi kullanabilirsiniz Collection
:
ISBN other = new ISBN("0-201-63361-2");
books.removeIf(b -> b.getIsbn().equals(other));
Veya yeni akış API'sını kullanın:
ISBN other = new ISBN("0-201-63361-2");
List<Book> filtered = books.stream()
.filter(b -> b.getIsbn().equals(other))
.collect(Collectors.toList());
Bu son durumda, öğeleri bir koleksiyondan filtrelemek için, orijinal referansı filtrelenmiş koleksiyona yeniden atayabilirsiniz (yani books = filtered
) veya filtrelenmiş koleksiyonu removeAll
orijinal koleksiyondaki (yani books.removeAll(filtered)
) bulunan öğelere yeniden kullanırsınız .
Alt Liste veya Altküme Kullan
Başka alternatifler de var. Liste sıralıysa ve art arda gelen öğeleri kaldırmak istiyorsanız bir alt liste oluşturabilir ve listeyi temizleyebilirsiniz:
books.subList(0,5).clear();
Alt liste orijinal liste ile desteklendiğinden, bu, öğelerin bu alt toplanmasını kaldırmanın etkili bir yolu olacaktır.
Benzer bir şey NavigableSet.subSet
yöntemi kullanarak sıralı kümelerle veya orada sunulan dilimleme yöntemlerinden herhangi biri ile elde edilebilir .
hususlar:
Hangi yöntemi kullandığınız, ne yapmak istediğinize bağlı olabilir
removeAl
Koleksiyon ve teknik herhangi bir Koleksiyon (Koleksiyon, Liste, Set, vb.) İle çalışır.
ListIterator
Teknik, açıkça, kendilerine verilen şartıyla listeleri ile çalışır ListIterator
uygulama teklifler eklemek ve kaldırmak işlemleri için destekler.
Iterator
Yaklaşım koleksiyonun her türlü ile çalışacak, ama bu kaldırma işlemlerini destekleyen tek.
- İle
ListIterator
/ Iterator
bariz avantajı biz yineleme olarak kaldırmak beri hiçbir şey kopyalamak zorunda değildir yaklaşır. Yani, bu çok verimli.
- JDK 8 akış örneği aslında hiçbir şeyi kaldırmadı, ancak istenen öğeleri aradık ve orijinal koleksiyon referansını yenisiyle değiştirdik ve eskisinin çöp toplanmasına izin verdik. Yani, koleksiyon üzerinde sadece bir kez tekrarlıyoruz ve bu verimli olacaktır.
- Toplama ve
removeAll
yaklaşımda dezavantaj iki kez yinelememiz gerektiğidir. İlk olarak, foop-döngüsünde kaldırma ölçütlerimizle eşleşen bir nesneyi ararız ve onu bulduktan sonra, orijinal koleksiyondan kaldırmayı isteriz, bu da bu öğeyi aramak için ikinci bir yineleme çalışması anlamına gelir. onu kaldır.
Iterator
Arayüz kaldırma yönteminin Javadocs'ta "isteğe bağlı" olarak işaretlendiğinden bahsetmeye değer olduğunu düşünüyorum, bu da kaldırma yöntemini çağırdığımızda Iterator
atılan uygulamalar olabileceği anlamına gelir UnsupportedOperationException
. Bu nedenle, elemanların kaldırılması için yineleyici desteğini garanti edemezsek, bu yaklaşımın diğerlerinden daha az güvenli olduğunu söyleyebilirim.