Java List.add () DesteklenmeyenOperationException


225

Bir List<String>örneğe nesne eklemeye çalışıyorum ama bir atar UnsupportedOperationException. Nedenini bilen var mı?

Java kodum:

String[] membersArray = request.getParameterValues('members');
List<String> membersList = Arrays.asList(membersArray);

for (String member : membersList) {
    Person person = Dao.findByName(member);
    List<String> seeAlso;
    seeAlso = person.getSeeAlso();
    if (!seeAlso.contains(groupDn)){
        seeAlso.add(groupDn);
        person.setSeeAlso(seeAlso);
    }
}

Hata mesajı:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add (Bilinmeyen Kaynak)
    java.util.AbstractList.add (Bilinmeyen Kaynak)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)

Yanıtlar:


458

Her Listuygulama add()yöntemi desteklemez .

Yaygın bir örneği Listtarafından döndürülen Arrays.asList()belgelenmiştir: değil (yani, çıkarma ya da elemanları ekleme) (vurgu madeni) herhangi bir yapısal değişiklik desteklemek için:

Belirtilen dizi tarafından desteklenen sabit boyutlu bir liste döndürür .

ListDeğiştirmeye çalıştığınız özellik bu olmasa bile , cevap hala Listdeğiştirilemeyen veya yalnızca seçilen değişikliklere izin veren diğer uygulamalar için geçerlidir .

Bunun belgelerini UnsupportedOperationExceptionve List.add()bunun hangi belgelerin "(isteğe bağlı işlem)" olduğunu okuyarak öğrenebilirsiniz . Bu ifadenin kesin anlamı Listdokümantasyonun üst kısmında açıklanmaktadır .

Geçici bir çözüm olarak, listenin aşağıdaki gibi bilinen değiştirilebilir bir uygulamaya kopyasını oluşturabilirsiniz ArrayList:

seeAlso = new ArrayList<>(seeAlso);

1
bu yüzden bir öğe eklemek zorunda benim öğe ve dizi örneği içerip içermediğini test etmek için liste örneği kullanmak zorunda? Bu yaz?
FAjir

90
@Florito: Bu işe yarayacak: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
mre

ya da benim List nesnesini ArrayList ya da başka bir döküm yapmak zorunda?
FAjir

2
Hayır gerçek değil. Eklemeye Listizin vermeyen bir uygulamaya bir öğe eklemek istiyorsanız List, bunu ( ArrayListortak bir aday olan) bir uygulamaya kopyalayıp eklemeniz gerekir.
Joachim Sauer

8

Liste uygulamasının çoğu, ekleme / kaldırma için sınırlı desteği destekler ve Arrays.asList (membersArray) bunlardan biridir. Kaydı java.util.ArrayList'e eklemeniz veya ArrayList'e dönüştürmek için aşağıdaki yaklaşımı kullanmanız gerekir.

Kodunuzdaki minimum değişiklikle, bir listeyi ArrayList'e dönüştürmek için aşağıda yapabilirsiniz. İlk çözüm, çözümünüzde minimum bir değişiklik yapmaktır, ancak ikincisi daha optimize edilmiştir, sanırım.

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));

VEYA

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));

4

Kalıtım kavramını oluşturma, Geçerli sınıfta bazı pertiküler yöntem yoksa, süper sınıflarda bu yöntemi arayacaktır. Varsa yürütür.

Atanan AbstractList<E>sınıf add()yöntemini uygular UnsupportedOperationException.


Bir Diziden Koleksiyon Obejct'e dönüştürürken. Yani, dizi tabanlı koleksiyon tabanlı dizi tabanlı, o zaman sabit boyutlu toplama nesnesi sağlayacaktır, çünkü Array'ın davranışı Sabit boyuttadır.

java.util.Arrays.asList (T ... a)

Konformasyon için sos örnekleri.

public class Arrays {
    public static <T> List<T> asList(T... a) {
        return new java.util.Arrays.ArrayList.ArrayList<>(a); // Arrays Inner Class ArrayList
    }
    //...
    private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
        //...
    }
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //...
    }

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }
    private class ListItr extends Itr implements ListIterator<E> {
        //...
    }
}

Yukarıdaki kaynağı oluşturup java.util.Arrays.ArrayListsınıfta olmadığını gözlemleyebilirsiniz @Override add(index, element), set(index, element), remove(index). Yani, kalıtımdan atar süper AbstractList<E>sınıf add()işlevi yürütür UnsupportedOperationException.

As AbstractList<E>it için uygulanmasını sağlayan soyut bir sınıftır iterator() and listIterator(). Böylece, liste nesnesi üzerinde yineleme yapabiliriz.

List<String> list_of_Arrays = Arrays.asList(new String[] { "a", "b" ,"c"});

try {
    list_of_Arrays.add("Yashwanth.M");
} catch(java.lang.UnsupportedOperationException e) {
    System.out.println("List Interface executes AbstractList add() fucntion which throws UnsupportedOperationException.");
}
System.out.println("Arrays → List : " + list_of_Arrays);

Iterator<String> iterator = list_of_Arrays.iterator();
while (iterator.hasNext()) System.out.println("Iteration : " + iterator.next() );

ListIterator<String> listIterator = list_of_Arrays.listIterator();
while (listIterator.hasNext())    System.out.println("Forward  iteration : " + listIterator.next() );
while(listIterator.hasPrevious()) System.out.println("Backward iteration : " + listIterator.previous());

Koleksiyonlar sınıfı için Sabit Boyutlu dizi formu bile oluşturabilirsiniz Collections.unmodifiableList(list);

Örnek Kaynak:

public class Collections {
    public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }
}

A Collection- bazen kap olarak da adlandırılır - birden çok öğeyi tek bir birimde gruplayan bir nesnedir. Koleksiyonlar, toplu verileri depolamak, almak, değiştirmek ve iletmek için kullanılır.

@Ayrıca bakınız


3

Listenizi başlatmalısınız.

List<String> seeAlso = new Vector<String>();

veya

List<String> seeAlso = new ArrayList<String>();

2
Başlatılmamış değişken neden olmaz UnsupportedOperationExceptioniçinde add(). Bunun yerine bir NPE alırsınız.
Stephen C

0

MembersList = Arrays.asList (membersArray) öğesini listele;

değişmez liste döndürür, yapmanız gereken şey

yeni ArrayList <> (Arrays.asList (membersArray)); değişebilir yapmak


Bu değişmez bir liste değil. Liste uzunluğunu değiştirmeyen mutasyon işlemleri desteklenir / çalışır. Önemli olan, listenin uzunluğu değişemediği için listenin uzunluğunun değişememesidir.
Stephen C

-1

add () kullanmak yerine addall () kullanabiliriz

{ seeAlso.addall(groupDn); }

add, tek bir öğe eklerken, addAll koleksiyondaki her öğeyi tek tek ekler. Sonuçta, koleksiyon değiştirilmişse her iki yöntem de true değerini döndürür. ArrayList durumunda bu önemsizdir, çünkü koleksiyon her zaman değiştirilir, ancak Set gibi diğer koleksiyonlar eklenmiş öğeler zaten oradaysa false döndürebilir.


-3

LDAP sorgusundan bir sonucu değiştiremezsiniz. Sorununuz şu satırda:

seeAlso.add(groupDn);

SeeAlso listesi değiştirilemez.


1
sorun bundan kaynaklanmıyor, ancak Joachim'in yukarıda belirttiği gibi, add () öğesini desteklemeyebilecek Liste uygulamaları ile ilgilidir.
Liv
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.