Arrays.asList () tarafından oluşturulan Listede remove (), UnsupportedOperationException atar


91

Bir koleksiyonum c1<MyClass>ve bir dizim var a<MyClass>. Diziyi bir koleksiyona dönüştürmeye çalışıyorum c2ve yapıyorum c1.removeAll(c2)ama bu fırlatıyor UnsupportedOperationException. Ben bulundu asList()Diziler sınıf döner ait Arrays.ArrayListsınıf ve bu sınıfın miras removeAll()dan AbstractList()kimin uygulama atar UnsupportedOperationException.

    Myclass la[] = getMyClass();
    Collection c = Arrays.asList(la);
    c.removeAll(thisAllreadyExistingMyClass);

Öğeleri kaldırmanın bir yolu var mı? lütfen yardım et


Yanıtlar:


173

Arrays.asListListbir dizi etrafında bir sarmalayıcı döndürür . Bu sarmalayıcı sabit bir boyuta sahiptir ve doğrudan dizi tarafından desteklenir ve bu nedenle, bu tür çağrılar setdiziyi değiştirecek ve listeyi değiştiren diğer herhangi bir yöntem bir UnsupportedOperationException.

Bunu düzeltmek için, sarmalayıcı listesinin içeriğini kopyalayarak yeni bir değiştirilebilir liste oluşturmanız gerekir. Bu kullanarak yapmak kolaydır ArrayListbir alan kurucuya Collection:

Collection c = new ArrayList(Arrays.asList(la));

1
java.util.Arrays asList()Yöntemin kaynak koduna bakıyordum ve bir ArrayList. Ancak, bir System.out.println(list.getClass());yaptığımda, alırım class java.util.Arrays$ArrayList. Bu nedenle, ArrayListbir addveya removeyöntemi olmayan iç sınıfı kullanır . Merak ediyorum ArrayList, java.util.ArrayListbirini kullanmak yerine içsel bir sınıfa sahip olmanın ne anlamı var ve neden bir add()ve remove()yöntemi yok?
Abdul

Yukarıdaki yorumumun düzeltmesi: bir addve removeyöntemi var
Abdul

1
@Abdul Çünkü sabit ölçü diye bir şey yok java.util.ArrayList. Sen bir uygulama istiyoruz Listki (ekleme veya kaldırma gibi) onunla yasadışı bir şey yaparsanız bir istisna atar ve ArrayListbu gereksinimi karşılamak değildir.
Etienne de Martel

@Abdul Arrays.asListsadece bir sarmalayıcı oluşturur List. Ama yine de bir java.util.List, bu yüzden bu yöntemlere sahip olmalı. Ancak uygulanamazlar çünkü bu, farklı boyutta yeni bir dizi oluşturmaya yol açar. Bu yapılamaz çünkü yapabileceğiniz değişiklikler hem döndürülen Liste hem de orijinal dizi aracılığıyla yapılabilir. Eğer döndürülen Liste değişebiliyorsa bu mümkün olmayacaktır, böylece temelde orijinal dizi referansını atacaktır.
Adam Hošek

13

Evet, Arrays.asList(..)genişletilemeyen veya küçültülemeyen is koleksiyonu (çünkü orijinal dizi tarafından destekleniyor ve yeniden boyutlandırılamıyor).

Öğeleri kaldırmak istiyorsanız ya bir öğe oluşturun new ArrayList(Arrays.asList(..)ya da öğeleri doğrudan diziden kaldırın (bu daha az verimli ve yazması daha zor olacaktır)


+1 Bu cevap tek doğru cevaptır: Arrays.asList () değiştirilemez bir liste döndürür - istisnayı ortaya çıkaran da budur. Bunun "bir dizi tarafından desteklenmesi" vb. İle ilgisi yoktur ... tüm Dizi Listeleri diziler tarafından desteklenir - önemli.
Bohemian

1
Ancak dokümanları daha fazla okursanız, aslında değiştirilemez olduğunu anlarsınız ... "Belirtilen dizi tarafından desteklenen sabit boyutlu bir liste döndürür. (Döndürülen listedeki değişiklikler, diziye" yazma " .) "-1, Etienne oldukça haklı.
Steven Schlansker

1
@Steven Evet, bu yüzden "değiştirilemez" veya "salt okunur" yerine "sabit boyut" diyor. Aslında, cevabımı şimdi bunu yansıtacak şekilde düzenleyeceğim.
Etienne de Martel

1
@Bohemian, Dönen koleksiyonlar aslında 'değiştirilebilir' çünkü 'set' yöntemini çağırmak mümkün.
javalearner

2
Bu şekilde nit seçecekseniz, "kodda bir throw UnsupportedOperationException ifadesi olduğu için UnsupportedOperationException atıyor" gibi boş şeyler de söyleyebilirsiniz. Bir API'nin tüketicileri, hangi AbstractBlah üst sınıfının bir istisna oluşturduğunu umursamıyor, kullandıkları sınıfın sözleşmelerinin ve beklentilerinin ne olduğunu önemsiyorlar. JVM v + 1'de istisnanın atıldığı yerde sınıf kitaplığının değişmesi tamamen mümkündür - ancak sözleşme değişmeyecektir.
Steven Schlansker

7

Bu şekilde Array.asList()çalışır, çünkü doğrudan dizi tarafından desteklenir. Tamamen değiştirilebilir bir liste elde etmek için, koleksiyonu kendi oluşturduğunuz bir koleksiyona klonlamanız gerekir.

Collection c = new ArrayList(Arrays.asList(la))

1
Liste değiştirilebilir ancak yalnızca set () aracılığıyla değiştirilebilir. döndürülen koleksiyon sabit boyuttadır.
javalearner

Aslında değiştirilemez olduğunu asla söylemedim. Sadece (tamamen) değiştirilebilir bir liste elde etmek için bir ArrayList. Yine de fark çok net değildi. :-) Listenin değiştirilebilir olup olmadığı bir tanım meselesi, "yarı değiştirilebilir" ama benim görüşüme göre tamamen değiştirilemez.
henko
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.