Java List.add () UnsupportedOperationException


225

Provo ad aggiungere oggetti a List<String>un'istanza ma genera un UnsupportedOperationException. Qualcuno sa perché?

Il mio codice Java:

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

Il messaggio di errore:

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

Risposte:


457

Non tutte le Listimplementazioni supportano il add()metodo.

Un esempio comune è il Listrestituito da Arrays.asList(): è documentato per non supportare alcuna modifica strutturale (es. Rimozione o aggiunta di elementi) (sottolineatura mia):

Restituisce un elenco di dimensioni fisse supportato dall'array specificato.

Anche se questo non è lo specifico Listche stai tentando di modificare, la risposta si applica comunque ad altre Listimplementazioni che sono immutabili o consentono solo alcune modifiche selezionate.

Puoi scoprirlo leggendo la documentazione di UnsupportedOperationExceptione List.add(), che documenta come "(operazione opzionale)". Il significato preciso di questa frase è spiegato nella parte superiore della Listdocumentazione.

Per ovviare al problema, puoi creare una copia dell'elenco in un'implementazione modificabile nota come ArrayList:

seeAlso = new ArrayList<>(seeAlso);

1
quindi devo usare l'istanza dell'elenco per verificare se contiene il mio elemento e l'istanza dell'array quando devo aggiungere un elemento? quello è scrivere?
FAjir,

90
@Florito: Funzionerà però: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
martedì

o forse devo lanciare il mio oggetto List su ArrayList o su un altro?
FAjir,

2
No, non proprio. Se vuoi aggiungere un elemento a Listun'implementazione che non consente l'aggiunta, dovrai copiarlo Listin un'implementazione che lo fa ( ArrayListè un candidato comune) e aggiungerlo a quello.
Joachim Sauer,

8

Molti dell'implementazione di List supportano un supporto limitato da aggiungere / rimuovere, e Arrays.asList (membersArray) è uno di questi. È necessario inserire il record in java.util.ArrayList o utilizzare l'approccio seguente per convertire in ArrayList.

Con la minima modifica del codice, è possibile effettuare le seguenti operazioni per convertire un elenco in ArrayList. La prima soluzione sta avendo un minimo cambiamento nella tua soluzione, ma la seconda è più ottimizzata, immagino.

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

O

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

4

Forma il concetto di ereditarietà. Se un metodo perticolare non è disponibile nella classe corrente, cercherà quel metodo in superclassi. Se disponibile, viene eseguito.

Esegue il metodo di AbstractList<E>classe add()che genera UnsupportedOperationException.


Quando si esegue la conversione da una matrice a una raccolta Obejct. ovvero, basato sull'array basato sull'API basata sulla raccolta, fornirà un oggetto raccolta di dimensioni fisse, poiché il comportamento dell'array è di dimensioni fisse.

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

Souce campioni per conformazione.

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

Da quanto sopra puoi osservare che la java.util.Arrays.ArrayListclasse no @Override add(index, element), set(index, element), remove(index). Quindi, dall'ereditarietà esegue la funzione di super AbstractList<E>classe add()che genera UnsupportedOperationException.

Come AbstractList<E>è una classe astratta che fornisce l'implementazione a iterator() and listIterator(). In modo che possiamo iterare sull'oggetto elenco.

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

Puoi persino creare un array a dimensione fissa dalla classe Collezioni Collections.unmodifiableList(list);

Fonte campione:

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- a volte chiamato contenitore - è semplicemente un oggetto che raggruppa più elementi in una singola unità. Le raccolte vengono utilizzate per archiviare, recuperare, manipolare e comunicare dati aggregati.

@Guarda anche


3

È necessario inizializzare il proprio elenco. Vedere anche:

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

o

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

2
Una variabile non inizializzata non causerà UnsupportedOperationExceptionin add(). Invece otterresti un NPE.
Stephen C

0

List membersList = Arrays.asList (membersArray);

restituisce un elenco immutabile, quello che devi fare è

new ArrayList <> (Arrays.asList (membersArray)); per renderlo mutabile


Non è un elenco immutabile. Le operazioni di mutazione che non modificano la lunghezza dell'elenco sono supportate / funzioneranno. La cosa fondamentale è che la lunghezza dell'elenco non può cambiare perché l'elenco è supportato da un array ... la cui lunghezza non può cambiare.
Stephen C

-1

invece di usare add () possiamo usare addall ()

{ seeAlso.addall(groupDn); }

add aggiunge un singolo elemento, mentre addAll aggiunge ogni elemento della raccolta uno per uno. Alla fine, entrambi i metodi restituiscono true se la raccolta è stata modificata. Nel caso di ArrayList questo è banale, perché la raccolta è sempre modificata, ma altre raccolte, come Set, possono restituire false se gli elementi aggiunti sono già presenti.


-3

Non è possibile modificare un risultato da una query LDAP. Il tuo problema è in questa linea:

seeAlso.add(groupDn);

L'elenco seeAlso non è modificabile.


1
il problema non è dovuto a questo, ma come Joachim ha sottolineato sopra, ha a che fare con le implementazioni di List che potrebbero non supportare add ().
Liv
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.