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.AbstractList.add (неизвестный источник)
    java.util.AbstractList.add (неизвестный источник)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service (HttpServlet.java:722)
FAjir
источник

Ответы:

457

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

Одним из распространенных примеров является Listвозвращаемое Arrays.asList(): документально подтверждено, что он не поддерживает какие-либо структурные изменения (например, удаление или добавление элементов) (выделено мной):

Возвращает список фиксированного размера, подкрепленный указанным массивом.

Даже если Listвы не пытаетесь это изменить, ответ по-прежнему относится к другим Listреализациям, которые либо неизменны, либо допускают только некоторые выбранные изменения.

Вы можете узнать об этом, прочитав документацию UnsupportedOperationExceptionи List.add(), какие документы это «(необязательная операция)». Точное значение этой фразы объясняется в верхней части Listдокументации.

В качестве обходного пути вы можете создать копию списка в известной изменяемой реализации, например ArrayList:

seeAlso = new ArrayList<>(seeAlso);
Йоахим Зауэр
источник
1
поэтому я должен использовать экземпляр списка, чтобы проверить, содержит ли он мой элемент и экземпляр массива, когда мне нужно добавить элемент? что пишешь?
Фаджир,
90
@Florito: Это будет работать, хотя: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
MRE
или, может быть, я должен привести свой объект List к ArrayList или другому?
Фаджир,
2
Нет, не совсем. Если вы хотите добавить в реализацию элемент List, который не допускает добавление, вам придется скопировать Listего в реализацию, которая делает ( ArrayListявляется общим кандидатом), и добавить к этому.
Иоахим Зауэр
8

Многие из реализации List поддерживают ограниченную поддержку для добавления / удаления, и одним из них является 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));
krmanish007
источник
4

Сформируйте концепцию наследования. Если какой-либо перикулярный метод недоступен в текущем классе, он будет искать этот метод в суперклассах. Если доступно, оно выполняется.

Он выполняет метод AbstractList<E>класса, add()который бросает UnsupportedOperationException.


Когда вы конвертируете из массива в коллекционный объект. то есть, на основе массива к API на основе коллекции, то он предоставит вам объект коллекции фиксированного размера, потому что поведение массива имеет фиксированный размер.

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 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 вместо этого.
Стивен С.
0

List membersList = Arrays.asList (membersArray);

возвращает неизменный список, что вам нужно сделать, это

новый ArrayList <> (Arrays.asList (membersArray)); сделать его изменчивым

Ziv.Ti
источник
Это не неизменный список. Операции мутации, которые не изменяют длину списка, поддерживаются / будут работать. Ключевым моментом является то, что длина списка не может измениться, потому что список поддерживается массивом ... длина которого не может измениться.
Стивен С
-1

вместо использования add () мы можем использовать addall ()

{ seeAlso.addall(groupDn); }

add добавляет один элемент, а addAll добавляет каждый элемент из коллекции один за другим. В конце оба метода возвращают true, если коллекция была изменена. В случае ArrayList это тривиально, поскольку коллекция всегда изменяется, но другие коллекции, такие как Set, могут возвращать false, если добавляемые элементы уже существуют.

Аллен
источник
-3

Вы не можете изменить результат из запроса LDAP. Ваша проблема в этой строке:

seeAlso.add(groupDn);

Список seeAlso также не подлежит изменению.

nfechner
источник
1
проблема не в этом, а в том, как указал выше Joachim, это связано с реализациями List, которые могут не поддерживать add ().
Лив,