简体   繁体   English

Java List.add() UnsupportedOperationException

[英]Java List.add() UnsupportedOperationException

I try to add objects to a List<String> instance but it throws an UnsupportedOperationException .我尝试将对象添加到List<String>实例,但它抛出UnsupportedOperationException Does anyone know why?有谁知道为什么?

My Java code:我的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);
    }
}

The error message:错误信息:

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

Not every List implementation supports the add() method.并非每个List实现都支持add()方法。

One common example is the List returned by Arrays.asList() : it is documented not to support any structural modification (ie removing or adding elements) (emphasis mine):一个常见的例子是Arrays.asList()返回的List :它被记录为支持任何结构修改(即删除或添加元素)(强调我的):

Returns a fixed-size list backed by the specified array.返回由指定数组支持的固定大小列表。

Even if that's not the specific List you're trying to modify, the answer still applies to other List implementations that are either immutable or only allow some selected changes.即使这不是您要修改的特定List ,答案仍然适用于其他不可变或仅允许某些选定更改的List实现。

You can find out about this by reading the documentation of UnsupportedOperationException and List.add() , which documents this to be an "(optional operation)".您可以通过阅读UnsupportedOperationExceptionList.add()的文档来了解这一点,其中将其记录为“(可选操作)”。 The precise meaning of this phrase is explained at the top of the List documentation.该短语的确切含义在List文档的顶部进行了解释。

As a workaround you can create a copy of the list to a known-modifiable implementation like ArrayList :作为一种解决方法,您可以将列表的副本创建为已知的可修改实现,例如ArrayList

seeAlso = new ArrayList<>(seeAlso);

Many of the List implementation support limited support to add/remove, and Arrays.asList(membersArray) is one of that.许多 List 实现支持对添加/删除的有限支持,Arrays.asList(membersArray) 就是其中之一。 You need to insert the record in java.util.ArrayList or use the below approach to convert into ArrayList.您需要在 java.util.ArrayList 中插入记录或使用以下方法转换为 ArrayList。

With the minimal change in your code, you can do below to convert a list to ArrayList.通过对代码进行最小的更改,您可以执行以下操作将列表转换为 ArrayList。 The first solution is having a minimum change in your solution, but the second one is more optimized, I guess.第一个解决方案对您的解决方案进行了最小的更改,但我想第二个解决方案更加优化。

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

OR或者

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

Form the Inheritance concept, If some perticular method is not available in the current class it will search for that method in super classes.形成继承概念,如果某些特定方法在当前类中不可用,它将在超类中搜索该方法。 If available it executes.如果可用,它会执行。

It executes AbstractList<E> class add() method which throws UnsupportedOperationException .它执行AbstractList<E>add()方法,该方法抛出UnsupportedOperationException


When you are converting from an Array to a Collection Obejct.当您从数组转换为集合对象时。 ie, array-based to collection-based API then it is going to provide you fixed-size collection object, because Array's behaviour is of Fixed size.即,基于数组到基于集合的 API 那么它将为您提供固定大小的集合对象,因为 Array 的行为是固定大小的。

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

Souce samples for conformation.用于构象的源样品。

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

Form the above Source you may observe that java.util.Arrays.ArrayList class doesn't @Override add(index, element), set(index, element), remove(index) .从上面的 Source 中,您可能会观察到java.util.Arrays.ArrayList类没有@Override add(index, element), set(index, element), remove(index) So, From inheritance it executes super AbstractList<E> class add() function which throws UnsupportedOperationException .因此,从继承它执行 super AbstractList<E> class add()函数,该函数抛出UnsupportedOperationException

As AbstractList<E> is an abstract class it provides the implementation to iterator() and listIterator() .由于AbstractList<E>是一个抽象类,它提供了iterator() and listIterator() So, that we can iterate over the list object.所以,我们可以遍历列表对象。

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

You can even create Fixed-Size array form Collections class Collections.unmodifiableList(list);你甚至可以创建固定大小的数组形式集合类Collections.unmodifiableList(list);

Sample Source:样本来源:

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 — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collection ——有时也称为容器——只是一个将多个元素组合成一个单元的对象。 Collections are used to store, retrieve, manipulate, and communicate aggregate data.集合用于存储、检索、操作和交流聚合数据。

@see also @也可以看看

You will also get this exception if you attempt to add to a List<T> returned by Collections.singletonList(T o) :如果您尝试addCollections.singletonList(T o)返回的List<T>您也会收到此异常:

Returns an immutable list containing only the specified object.返回仅包含指定对象的不可变列表。 The returned list is serializable.返回的列表是可序列化的。

The JVM does not implement add() for Collections.singletonList JVM 没有为Collections.singletonList实现add()

You must initialize your List seeAlso :您必须初始化您的 List seeAlso :

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

or或者

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

List membersList = Arrays.asList(membersArray); List membersList = Arrays.asList(membersArray);

returns immutable list, what you need to do is返回不可变列表,你需要做的是

new ArrayList<>(Arrays.asList(membersArray));新 ArrayList<>(Arrays.asList(membersArray)); to make it mutable使其可变

You cannot modify a result from a LDAP query.您不能修改 LDAP 查询的结果。 Your problem is in this line:你的问题在这一行:

seeAlso.add(groupDn);

The seeAlso list is unmodifiable. seeAlso 列表是不可修改的。

instead of using add() we can use addall()我们可以使用 addall() 代替 add()

{ seeAlso.addall(groupDn); }

add adds a single item, while addAll adds each item from the collection one by one. add 添加单个项目,而 addAll 一个一个地添加集合中的每个项目。 In the end, both methods return true if the collection has been modified.最后,如果集合已被修改,两种方法都返回 true。 In case of ArrayList this is trivial, because the collection is always modified, but other collections, such as Set, may return false if items being added are already there.在 ArrayList 的情况下,这是微不足道的,因为集合总是被修改,但是如果要添加的项目已经存在,则其他集合(例如 Set)可能会返回 false。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM