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)

Answers:


457

并非每个List实现都支持该add()方法。

一个常见的示例是通过以下方式List返回的Arrays.asList():它被记录为支持任何结构修改(即,删除或添加元素)(强调我的意思):

返回由指定数组支持的固定大小的列表。

即使这不是List您要修改的特定内容,答案仍然适用于List不可变或仅允许某些选定更改的其他实现。

您可以通过阅读的文档,了解这个UnsupportedOperationExceptionList.add(),其中记录了这是一个“(可选操作)”。该短语的确切含义在List文档顶部进行了说明。

解决方法是,您可以将列表的副本创建到一个已知的可修改的实现中,例如ArrayList

seeAlso = new ArrayList<>(seeAlso);

1
所以当我必须添加一个元素时,我必须使用列表实例来测试它是否包含我的元素和数组实例?那是写的吗?
FAjir 2011年

90
@Florito:虽然可以使用:List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres));:)
mre11年

还是我必须将List对象转换为ArrayList或另一个?
FAjir 2011年

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

4

从继承概念开始,如果当前类中没有某些垂直方法,它将在超类中搜索该方法。如果可用,它将执行。

它执行throw的AbstractList<E>add()方法UnsupportedOperationException


从数组转换为集合对象时。即基于数组的API到基于集合的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> {
        //...
    }
}

从上面的Source中,您可能会发现java.util.Arrays.ArrayList该类没有@Override add(index, element), set(index, element), remove(index)。因此,从继承开始,它执行throw的超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));
    }
}

A Collection(有时称为容器)只是将多个元素组合为一个单元的对象。集合用于存储,检索,操作和传达聚合数据。

@也可以看看


3

您必须初始化List seeAlso:

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

要么

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

2
未初始化的变量会不会造成UnsupportedOperationExceptionadd()。您将获得一个NPE。
斯蒂芬·C

0

列出memberList = Arrays.asList(membersArray);

返回不可变列表,您需要做的是

新的ArrayList <>(Arrays.asList(membersArray)); 使它可变


这不是一成不变的清单。支持/不会更改列表长度的变异操作。关键是列表的长度不能更改,因为列表由数组支持...数组的长度不能更改。
斯蒂芬·C

-1

代替使用add()我们可以使用addall()

{ seeAlso.addall(groupDn); }

add添加一个项目,而addAll则一个接一个地添加集合中的每个项目。最后,如果对集合进行了修改,则这两个方法均返回true。在ArrayList的情况下,这是微不足道的,因为该集合始终会被修改,但是其他集合(如Set)可能会返回false(如果正在添加的项已经存在)。


-3

您无法修改LDAP查询的结果。您的问题在这一行:

seeAlso.add(groupDn);

seeAlso列表不可修改。


1
问题不在于此,而正如Joachim上面指出的那样,与List的实现可能不支持add()有关。
Liv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.