Java List.add () UnsupportedOperationException

225

Ich versuche, einer List<String>Instanz Objekte hinzuzufügen, aber es wird eine ausgelöst UnsupportedOperationException. Weiß jemand warum?

Mein Java-Code:

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);
    }
}

Die Fehlermeldung:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add (Unbekannte Quelle)
    java.util.AbstractList.add (Unbekannte Quelle)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)
FAjir
quelle

Antworten:

457

Nicht jede ListImplementierung unterstützt die add()Methode.

Ein gängiges Beispiel ist die Listzurück durch Arrays.asList(): Es ist dokumentiert , nicht irgendeine strukturelle Änderung zu unterstützen (dh das Entfernen oder Hinzufügen von Elementen) (Hervorhebung von mir):

Gibt eine Liste mit fester Größe zurück, die vom angegebenen Array unterstützt wird.

Auch wenn dies nicht das Spezifische ist, das ListSie ändern möchten, gilt die Antwort dennoch für andere ListImplementierungen, die entweder unveränderlich sind oder nur einige ausgewählte Änderungen zulassen.

Sie können dies herausfinden, indem Sie die Dokumentation von UnsupportedOperationExceptionund lesen, die dokumentiert List.add(), dass es sich um eine "(optionale Operation)" handelt. Die genaue Bedeutung dieses Satzes wird oben in der ListDokumentation erläutert .

Als Abhilfe können Sie eine Kopie der Liste mit einer bekannten modifizierbaren Implementierung wie erstellen ArrayList:

seeAlso = new ArrayList<>(seeAlso);
Joachim Sauer
quelle
1
Also muss ich die Listeninstanz verwenden, um zu testen, ob sie mein Element enthält, und die Array-Instanz, wenn ich ein Element hinzufügen muss. das ist Schreiben?
FAjir
90
@ Florito: Dies wird jedoch funktionieren: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
mre
oder muss ich mein List-Objekt in ArrayList oder ein anderes umwandeln?
FAjir
2
Nein nicht wirklich. Wenn Sie einer ListImplementierung, die kein Hinzufügen zulässt, ein Element hinzufügen möchten, müssen Sie es in eine Implementierung kopieren, Listdie dies tut ( ArrayListein häufiger Kandidat ist), und es hinzufügen.
Joachim Sauer
8

Viele der List-Implementierungen unterstützen nur eingeschränkte Unterstützung für das Hinzufügen / Entfernen, und Arrays.asList (memberArray) ist eine davon. Sie müssen den Datensatz in java.util.ArrayList einfügen oder den folgenden Ansatz verwenden, um ihn in ArrayList zu konvertieren.

Mit der minimalen Änderung in Ihrem Code können Sie unten eine Liste in ArrayList konvertieren. Die erste Lösung hat eine minimale Änderung in Ihrer Lösung, aber die zweite ist vermutlich optimierter.

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

ODER

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

Bilden Sie das Vererbungskonzept. Wenn eine bestimmte Methode in der aktuellen Klasse nicht verfügbar ist, wird in Superklassen nach dieser Methode gesucht. Wenn verfügbar, wird es ausgeführt.

Es führt eine AbstractList<E>Klassenmethode aus add(), die auslöst UnsupportedOperationException.


Wenn Sie von einem Array in ein Sammlungsobjekt konvertieren. Wenn Sie also eine Array-basierte oder eine sammlungsbasierte API verwenden, erhalten Sie ein Sammlungsobjekt mit fester Größe, da das Verhalten des Arrays eine feste Größe hat.

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

Quellenproben für die Konformation.

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> {
        //...
    }
}

Wenn Sie die obige Quelle bilden, können Sie feststellen, dass diese java.util.Arrays.ArrayListKlasse dies nicht tut @Override add(index, element), set(index, element), remove(index). Also, von Vererbung führt es Super - AbstractList<E>Klasse - add()Funktion , die wirft UnsupportedOperationException.

Da AbstractList<E>es sich um eine abstrakte Klasse handelt, wird die Implementierung bereitgestellt iterator() and listIterator(). Damit wir über das Listenobjekt iterieren können.

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());

Sie können sogar Array-Formulare mit fester Größe aus Sammlungen erstellen Collections.unmodifiableList(list);

Beispielquelle:

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- manchmal auch Container genannt - ist einfach ein Objekt, das mehrere Elemente zu einer Einheit zusammenfasst. Sammlungen werden zum Speichern, Abrufen, Bearbeiten und Kommunizieren aggregierter Daten verwendet.

@siehe auch

Yash
quelle
3

Sie müssen Ihre Liste initialisieren. Siehe auch:

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

oder

List<String> seeAlso = new ArrayList<String>();
Dwayne
quelle
2
Eine nicht initialisierte Variable wird nicht dazu führen , UnsupportedOperationExceptionin add(). Sie würden stattdessen eine NPE erhalten.
Stephen C
0

Liste MembersList = Arrays.asList (MembersArray);

Gibt eine unveränderliche Liste zurück. Was Sie tun müssen, ist

neue ArrayList <> (Arrays.asList (membersArray)); um es veränderlich zu machen

Ziv.Ti
quelle
Es ist keine unveränderliche Liste. Mutationsoperationen, die die Listenlänge nicht ändern, werden unterstützt / funktionieren. Der Schlüssel ist, dass sich die Länge der Liste nicht ändern kann, da die Liste von einem Array unterstützt wird ... dessen Länge sich nicht ändern kann.
Stephen C
-1

Anstatt add () zu verwenden, können wir addall () verwenden.

{ seeAlso.addall(groupDn); }

add fügt ein einzelnes Element hinzu, während addAll jedes Element aus der Sammlung einzeln hinzufügt. Am Ende geben beide Methoden true zurück, wenn die Sammlung geändert wurde. Im Fall von ArrayList ist dies trivial, da die Auflistung immer geändert wird, andere Auflistungen wie Set jedoch möglicherweise false zurückgeben, wenn bereits hinzugefügte Elemente vorhanden sind.

Allen
quelle
-3

Sie können ein Ergebnis einer LDAP-Abfrage nicht ändern. Ihr Problem liegt in dieser Zeile:

seeAlso.add(groupDn);

Die seeAlso-Liste kann nicht geändert werden.

nfechner
quelle
1
Das Problem ist nicht darauf zurückzuführen, aber wie Joachim oben ausgeführt hat, handelt es sich um Implementierungen von List, die add () möglicherweise nicht unterstützen.
Liv