Java List.add () UnsupportedOperationException

225

Próbuję dodać obiekty do List<String>instancji, ale rzuca ona UnsupportedOperationException. Czy ktoś wie dlaczego?

Mój kod 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);
    }
}

Komunikat o błędzie:

java.lang.UnsupportedOperationException
    java.util.AbstractList.add (Nieznane źródło)
    java.util.AbstractList.add (Nieznane źródło)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)
FAjir
źródło

Odpowiedzi:

457

Nie każda Listimplementacja obsługujeadd() metodę.

Jednym z typowych przykładów jest Listzwracany przez Arrays.asList(): jest udokumentowane nie wspierać żadnych zmian strukturalnych (np usuwanie lub dodawanie elementów) (kopalni nacisk)

Zwraca stały rozmiar popartą określoną tablicą.

Nawet jeśli to nie jest specyficzne List którą próbujesz zmodyfikować, odpowiedź nadal dotyczy innychList implementacji, które są albo niezmienne, albo dopuszczają tylko niektóre wybrane zmiany.

Możesz się o tym dowiedzieć, czytając dokumentację UnsupportedOperationExceptioniList.add() , który dokumentuje to jako „(operacja opcjonalna)”. Dokładne znaczenie tego wyrażenia wyjaśniono na górzeList dokumentacji.

Aby obejść ten problem, możesz utworzyć kopię listy do znanej modyfikowalnej implementacji, takiej jak ArrayList:

seeAlso = new ArrayList<>(seeAlso);
Joachim Sauer
źródło
1
więc muszę użyć instancji listy, aby sprawdzić, czy zawiera ona mój element i instancję tablicy, gdy muszę dodać element? to pisze?
FAjir
90
@Florito: To będzie działać mimo: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
MRE
a może muszę rzutować mój obiekt List na ArrayList lub inny?
FAjir
2
Nie, nie bardzo. Jeśli chcesz dodać element do Listimplementacji, który nie pozwala na dodawanie, musisz skopiować Listgo do implementacji, która to robi ( ArrayListjest typowym kandydatem) i dodać do tego.
Joachim Sauer
8

Wiele implementacji List obsługuje ograniczoną obsługę dodawania / usuwania, a Arrays.asList (MembersArray) jest jednym z nich. Musisz wstawić rekord do java.util.ArrayList lub zastosować poniższe podejście, aby przekonwertować na ArrayList.

Przy minimalnej zmianie w kodzie możesz zrobić poniżej, aby przekonwertować listę na ArrayList. Pierwsze rozwiązanie ma minimalną zmianę w twoim rozwiązaniu, ale chyba drugie jest bardziej zoptymalizowane.

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

LUB

    String[] membersArray = request.getParameterValues('members');
    ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));
krmanish007
źródło
4

Stwórz koncepcję dziedziczenia, jeśli jakaś metoda perticular nie jest dostępna w bieżącej klasie, będzie szukała tej metody w superklasach. Jeśli jest dostępny, wykonuje się.

Wykonuje metodę AbstractList<E>klasy add(), która rzuca UnsupportedOperationException.


Podczas konwertowania z tablicy na Collection Obejct. tzn. oparty na macierzy na interfejsie API opartym na kolekcji, to zapewni ci obiekt kolekcji o stałym rozmiarze, ponieważ zachowanie tablicy ma stały rozmiar.

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

Próbki soku do konformacji.

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

Z powyższego źródła można zauważyć, że java.util.Arrays.ArrayListklasa nie @Override add(index, element), set(index, element), remove(index). Tak więc, od dziedziczenia wykonuje on super- AbstractList<E>klasy add()funkcji, która rzucaUnsupportedOperationException .

Jako AbstractList<E>klasa abstrakcyjna zapewnia implementację do iterator() and listIterator(). Abyśmy mogli iterować obiekt listy.

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

Możesz nawet utworzyć tablicę o stałej wielkości z klasy Kolekcje Collections.unmodifiableList(list);

Przykładowe źródło:

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

ZA Collection - czasami nazywany kontenerem - to po prostu obiekt, który grupuje wiele elementów w jedną jednostkę. Kolekcje służą do przechowywania, pobierania, manipulowania i komunikowania danych agregowanych.

@Zobacz też

Yash
źródło
3

Musisz zainicjować swoją listę patrz również:

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

lub

List<String> seeAlso = new ArrayList<String>();
dwayne
źródło
2
Zmienna niezainicjowany nie spowoduje UnsupportedOperationExceptionw add(). Zamiast tego dostałbyś NPE.
Stephen C
0

List MembersList = Arrays.asList (MembersArray);

zwraca niezmienną listę, co musisz zrobić

new ArrayList <> (Arrays.asList (MembersArray)); aby było to możliwe

Ziv.Ti
źródło
To nie jest niezmienna lista. Operacje mutacji, które nie zmieniają długości listy są obsługiwane / będą działać. Najważniejsze jest to, że długość listy nie może się zmienić, ponieważ lista jest wspierana przez tablicę ... której długości nie można zmienić.
Stephen C
-1

zamiast używać add () możemy użyć addall ()

{ seeAlso.addall(groupDn); }

add dodaje pojedynczy element, a addAll dodaje każdy element z kolekcji jeden po drugim. Ostatecznie obie metody zwracają wartość true, jeśli kolekcja została zmodyfikowana. W przypadku ArrayList jest to trywialne, ponieważ kolekcja jest zawsze modyfikowana, ale inne kolekcje, takie jak Set, mogą zwracać wartość false, jeśli dodawane elementy już tam są.

Allen
źródło
-3

Nie można zmodyfikować wyniku z zapytania LDAP. Twój problem jest następujący:

seeAlso.add(groupDn);

Lista seeAlso jest niemodyfikowalna.

nfechner
źródło
1
problem nie wynika z tego, ale, jak wskazał powyżej Joachim, dotyczy implementacji List, które mogą nie obsługiwać funkcji add ().
Liv