Java List.add () UnsupportedOperationException


225

Я намагаюся додати об'єкти до List<String>екземпляра, але він кидаєUnsupportedOperationException . Хтось знає, чому?

Мій код 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);
    }
}

Повідомлення про помилку:

java.lang.UnsupportedOperationException
    java.util.Ab абстрактList.add (невідоме джерело)
    java.util.Ab абстрактList.add (невідоме джерело)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)

Відповіді:


457

Не кожна Listреалізація підтримує add()метод.

Одним із поширених прикладів є Listповернення Arrays.asList(): задокументовано, що не підтримується будь-яка структурна модифікація (тобто видалення або додавання елементів) (моє наголос):

Повертає список фіксованого розміру, підкріплений вказаним масивом.

Навіть якщо це не конкретно, Listщо ви намагаєтеся змінити, відповідь все ж стосується інших Listреалізацій, які є незмінними або дозволяють лише деякі обрані зміни.

Ви можете дізнатися про це, прочитавши документацію UnsupportedOperationExceptionта List.add(), які документи це "(необов'язкова операція)". Точне значення цієї фрази пояснюється вгорі Listдокументації.

Як вирішення, ви можете створити копію списку для відомої модифікованої реалізації, наприклад ArrayList:

seeAlso = new ArrayList<>(seeAlso);

1
тому я повинен використовувати екземпляр списку, щоб перевірити, чи він містить мій елемент та екземпляр масиву, коли мені потрібно додати елемент? це написати?
FAjir

90
@Florito: Це спрацює, хоча: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
mre

чи, можливо, мені доведеться віддати свій список List до ArrayList чи іншого?
FAjir

2
Ні, не дуже. Якщо ви хочете додати елемент до Listреалізації, яка не дозволяє додавати, вам доведеться скопіювати це Listв реалізацію, яка ArrayListє ( є загальним кандидатом), і додати її.
Йоахім Зауер

8

Багато хто із впровадження списку підтримує обмежену підтримку додавання / видалення, а Arrays.asList (membersArray) є одним із них. Вам потрібно вставити запис у java.util.ArrayList або скористатися поданим нижче підходом для перетворення в ArrayList.

З мінімальними змінами коду, ви можете зробити нижче, щоб перетворити список у ArrayList. Перше рішення має мінімальні зміни у вашому рішенні, але друге є більш оптимізованим, я думаю.

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

АБО

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

4

Сформуйте концепцію спадкування, якщо якийсь пертикулярний метод недоступний у поточному класі, він шукатиме цей метод у суперкласах. При наявності він виконує.

Він виконує метод AbstractList<E>класу, add()який кидає UnsupportedOperationException.


При перетворенні з масиву в колекцію Obejct. тобто на основі масиву до API на основі колекції, тоді він надасть вам об'єкт колекції фіксованого розміру, оскільки поведінка Array має фіксований розмір.

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

Зразки соуса для конформації.

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

Сформувавши вищевказане джерело, ви можете спостерігати, що java.util.Arrays.ArrayListклас не відповідає @Override add(index, element), set(index, element), remove(index). Отже, з успадкування він виконує функцію супер AbstractList<E>класу, add()яка кидає UnsupportedOperationException.

Оскільки AbstractList<E>це абстрактний клас, він забезпечує його реалізацію iterator() and listIterator(). Отже, ми можемо перебрати об’єкт списку.

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

Ви навіть можете створити форму масиву масивів з фіксованим розміром Collections.unmodifiableList(list);

Зразок джерела:

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

А Collection- іноді називається контейнером - це просто об'єкт, який групує кілька елементів в одну одиницю. Колекції використовуються для зберігання, пошуку, маніпулювання та передачі сукупних даних.

@дивитися також


3

Ви повинні ініціалізувати свій Список див. Також:

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

або

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

2
Неініціалізована змінна не призведе UnsupportedOperationExceptionдо add(). Ви б отримали NPE замість цього.
Стівен C

0

Список membersList = Arrays.asList (membersArray);

повертає незмінний список, що вам потрібно зробити

новий ArrayList <> (Arrays.asList (membersArray)); зробити його змінним


Це не непорушний список. Мутаційні операції, які не змінюють довжину списку, підтримуються / працюватимуть. Ключовим є те, що довжина списку не може змінюватися, оскільки список підтримується масивом ... довжина якого не може змінитися.
Stephen C

-1

замість використання add () ми можемо використовувати addall ()

{ seeAlso.addall(groupDn); }

add додає один елемент, тоді як addAll додає кожен елемент із колекції по одному. Зрештою, обидва способи повертають істину, якщо колекція була змінена. У випадку ArrayList це тривіально, оскільки колекція завжди змінюється, але інші колекції, наприклад Set, можуть повернути помилкові, якщо елементи, які додаються, вже є.


-3

Ви не можете змінити результат запиту LDAP. Ваша проблема в цьому рядку:

seeAlso.add(groupDn);

Список seeAlso неможливо змінити.


1
проблема пов’язана не з цим, але, як зазначав Йоахім вище, це стосується реалізації Списку, яка може не підтримувати add ().
Лів
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.