Java List.add () UnsupportedOperationException


225

List<String>인스턴스 에 객체를 추가하려고 시도 하지만가 발생합니다 UnsupportedOperationException. 아무도 이유를 알고 있습니까?

내 자바 코드 :

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)

답변:


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하여 추가해야합니다.
Joachim Sauer

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

상속 개념을 형성하십시오. 현재 클래스에서 일부 perticular 메소드를 사용할 수 없으면 수퍼 클래스에서 해당 메소드를 검색합니다. 사용 가능한 경우 실행됩니다.

던지는 AbstractList<E>클래스 add()메소드를 실행 UnsupportedOperationException합니다.


Array에서 Collection Obejct로 변환 할 때 즉, 배열 기반의 컬렉션 기반 API에서 배열의 동작은 고정 크기이므로 고정 크기의 컬렉션 객체를 제공합니다.

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

형태를위한 Souce 샘플.

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를 초기화해야합니다.

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

또는

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

2
초기화되지 않은 변수는 UnsupportedOperationException에서 발생하지 않습니다 add(). 대신 NPE를 얻습니다.
Stephen C

0

List membersList = Arrays.asList (membersArray);

불변 목록을 반환합니다.

새로운 ArrayList <> (Arrays.asList (membersArray)); 변경 가능하도록


변경할 수없는 목록이 아닙니다. 목록 길이를 변경하지 않는 돌연변이 작업이 지원됩니다. 중요한 것은 목록이 길이를 변경할 수없는 배열에 의해 지원되기 때문에 목록의 길이를 변경할 수 없다는 것입니다.
Stephen C

-1

add ()를 사용하는 대신 addall ()을 사용할 수 있습니다

{ seeAlso.addall(groupDn); }

add는 단일 항목을 추가하는 반면 addAll은 컬렉션의 각 항목을 하나씩 추가합니다. 결국 컬렉션이 수정 된 경우 두 방법 모두 true를 반환합니다. ArrayList의 경우 컬렉션은 항상 수정되기 때문에 간단하지만 추가되는 항목이 이미 있으면 Set과 같은 다른 컬렉션은 false를 반환 할 수 있습니다.


-3

LDAP 쿼리에서 결과를 수정할 수 없습니다. 문제는 다음 줄에 있습니다.

seeAlso.add(groupDn);

seeAlso 목록도 수정할 수 없습니다.


1
문제는 그 때문이 아니지만 Joachim이 위에서 지적했듯이 add ()를 지원하지 않을 수있는 List 구현과 관련이 있습니다.
Liv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.