Programing

List에서 요소를 제거하려고 할 때 UnsupportedOperationException이 발생하는 이유는 무엇입니까?

lottogame 2020. 2. 18. 21:52
반응형

List에서 요소를 제거하려고 할 때 UnsupportedOperationException이 발생하는 이유는 무엇입니까?


이 코드가 있습니다 :

public static String SelectRandomFromTemplate(String template,int count) {
   String[] split = template.split("|");
   List<String> list=Arrays.asList(split);
   Random r = new Random();
   while( list.size() > count ) {
      list.remove(r.nextInt(list.size()));
   }
   return StringUtils.join(list, ", ");
}

나는 이것을 얻는다 :

06-03 15:05:29.614: ERROR/AndroidRuntime(7737): java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737):     at java.util.AbstractList.remove(AbstractList.java:645)

이것이 올바른 방법은 무엇입니까? 자바 .15


코드와 관련된 몇 가지 문제 :

Arrays.asList고정 된 크기의 목록을 반환

API에서 :

Arrays.asList: 지정된 배열이 지원 하는 고정 크기 목록을 반환합니다 .

당신은 add그것을 할 수 없습니다 ; 당신은 remove그것에서 할 수 없습니다 . 을 구조적으로 수정할 수 없습니다 List.

고치다

LinkedList더 빨리 지원하는를 만듭니다 remove.

List<String> list = new LinkedList<String>(Arrays.asList(split));

split정규식을 복용

API에서 :

String.split(String regex): 주어진 정규 표현식 과 일치하는 문자열을 분할합니다 .

|정규식 메타 문자입니다. 리터럴로 분할 |하려면 \|Java 문자열 리터럴 인 이스케이프로 이스케이프해야합니다 "\\|".

고치다:

template.split("\\|")

더 나은 알고리즘

remove임의의 인덱스를 사용하여 한 번에 하나씩 호출하는 대신 범위에서 충분한 임의의 숫자를 생성 한 다음 적절한 인덱스를 호출 하여을 사용하여 List한 번 순회하는 것이 좋습니다. 주어진 범위에서 임의의 고유 한 숫자를 생성하는 방법에 대한 질문이 있습니다.listIterator()remove()

이를 통해 알고리즘은입니다 O(N).


이건 나에게 여러 번 화상을 입었다. Arrays.asList수정할 수없는 목록을 만듭니다. Javadoc에서 : 지정된 배열이 지원 하는 고정 크기 목록을 리턴합니다 .

동일한 내용으로 새 목록을 만듭니다.

newList.addAll(Arrays.asList(newArray));

이렇게하면 약간의 추가 가비지가 생성되지만이를 변경할 수 있습니다.


수정 불가능한 래퍼로 작업하고 있기 때문일 수 있습니다 .

이 줄을 바꾸십시오 :

List<String> list = Arrays.asList(split);

이 줄에 :

List<String> list = new LinkedList<>(Arrays.asList(split));

나는 그것을 대체한다고 생각한다.

List<String> list = Arrays.asList(split);

List<String> list = new ArrayList<String>(Arrays.asList(split));

문제를 해결합니다.


asList 메소드에 대한 JavaDoc을 읽으십시오.

지정된 배열에있는 객체의 {@code List}를 반환합니다. {@code List}의 크기는 수정할 수 없습니다. 즉 추가 및 제거는 지원되지 않지만 요소는 설정할 수 있습니다. 요소를 설정하면 기본 배열이 수정됩니다.

이것은 Java 6에서 왔지만 안드로이드 java와 동일합니다.

편집하다

결과 목록의 유형은 Arrays.ArrayListArrays.class 내부의 개인 클래스입니다. 실제로 말하자면, 전달한 배열의 List-view에 지나지 않습니다 Arrays.asList. 결과적으로 배열을 변경하면 목록도 변경됩니다. 또한 배열 크기를 조정할 수 없으므로 제거 및 추가 작업 이 지원되지 않아야 합니다.


Arrays.asList ()는 크기에 영향을주는 작업을 허용하지 않는 목록을 반환합니다 ( "수정 불가능"과 동일하지 않음).

new ArrayList<String>(Arrays.asList(split));실제 사본을 만들 수는 있지만 수행하려는 작업을 볼 때 여기에 추가 제안 사항이 있습니다 ( O(n^2)알파벳 바로 아래에 알고리즘이 있음).

목록에서 임의의 요소 를 제거 list.size() - count(이것이라고 함 k) 하려고 합니다. 임의의 요소를 여러 개 선택 k하여 목록 의 끝 위치로 바꾸고 전체 범위를 삭제하십시오 (예 : subList () 및 clear () 사용). 그것은 그것을 희박하고 평균적인 O(n)알고리즘으로 바꿀 것 O(k)입니다 (보다 정확합니다).

업데이트 : 아래에 언급 된 것처럼이 알고리즘은 요소가 정렬되지 않은 경우 (예 : List가 Bag을 나타내는 경우에만) 의미가 있습니다. 반면에 목록에 의미있는 순서가있는 경우이 알고리즘은이를 유지하지 않습니다 (대신 다유 윤활제 알고리즘).

업데이트 2 : 따라서 돌이켜 보면 더 나은 (선형, 유지 순서, 그러나 임의의 O (n) 난수) 알고리즘은 다음과 같습니다.

LinkedList<String> elements = ...; //to avoid the slow ArrayList.remove()
int k = elements.size() - count; //elements to select/delete
int remaining = elements.size(); //elements remaining to be iterated
for (Iterator i = elements.iterator(); k > 0 && i.hasNext(); remaining--) {
  i.next();
  if (random.nextInt(remaining) < k) {
     //or (random.nextDouble() < (double)k/remaining)
     i.remove();
     k--;
  }
}

에 의해 반환 된 목록은 Arrays.asList()변경 불가능할 수 있습니다. 당신이 시도 할 수 있습니다

List<String> list = new ArrayList(Arrays.asList(split));

그 문제에 대한 또 다른 해결책이 있습니다.

List<String> list = Arrays.asList(split);
List<String> newList = new ArrayList<>(list);

newList;) 작업


이 UnsupportedOperationException은 컬렉션에서 허용되지 않는 컬렉션에서 일부 작업을 수행하려고 할 때 발생하며 호출 Arrays.asList할 때을 반환하지 않습니다 java.util.ArrayList. java.util.Arrays$ArrayList불변의리스트 인를 돌려줍니다 . 추가 할 수 없으며 제거 할 수 없습니다.


예,에 Arrays.asList고정 크기 목록을 반환합니다.

연결리스트를 사용하는 것 외에는 단순히 addAll메소드리스트 를 사용 하십시오.

예:

String idList = "123,222,333,444";

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

parentRecepeIdList.addAll(Arrays.asList(idList.split(","))); 

parentRecepeIdList.add("555");

다음은 배열의 코드 스 니펫입니다.

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

asList 메소드가 호출되면 AbstractList의 add 함수를 재정의하지 않고 배열에 요소를 저장하는 자체 정적 클래스 버전의 목록을 반환합니다. 따라서 기본적으로 추상 목록의 add 메소드는 예외를 발생시킵니다.

따라서 일반 배열 목록이 아닙니다.


고정 크기 목록의 배열을 제거하거나 추가 할 수 없습니다.

그러나 해당 목록에서 하위 목록을 만들 수 있습니다.

list = list.subList(0, list.size() - (list.size() - count));

public static String SelectRandomFromTemplate(String template, int count) {
   String[] split = template.split("\\|");
   List<String> list = Arrays.asList(split);
   Random r = new Random();
   while( list.size() > count ) {
      list = list.subList(0, list.size() - (list.size() - count));
   }
   return StringUtils.join(list, ", ");
}

* 다른 방법은

ArrayList<String> al = new ArrayList<String>(Arrays.asList(template));

이것은 Arrays.asList와 같이 고정 크기가 아닌 ArrayList를 만듭니다.


바꾸다

List<String> list=Arrays.asList(split);

List<String> list = New ArrayList<>();
list.addAll(Arrays.asList(split));

또는

List<String> list = new ArrayList<>(Arrays.asList(split));

또는

List<String> list = new ArrayList<String>(Arrays.asList(split));

또는 (요소 제거에 더 좋음)

List<String> list = new LinkedList<>(Arrays.asList(split));

Arraylist narraylist = Arrays.asList (); // 불변의 arraylist를 반환합니다. 변경 가능한 솔루션으로 만들려면 : Arraylist narraylist = new ArrayList (Arrays.asList ());


Arrays.asList()내부적으로 고정 크기 배열을 사용합니다.
동적으로 추가하거나 제거 할 수 없습니다Arrays.asList()

이것을 사용하십시오

Arraylist<String> narraylist=new ArrayList(Arrays.asList());

에서 narraylist당신은 쉽게 추가하거나 제거 항목 수 있습니다.


새 목록을 만들고 새 목록에 유효한 값을 채우면 나에게 도움이되었습니다.

코드 던지기 오류-

List<String> list = new ArrayList<>();
   for (String s: list) {
     if(s is null or blank) {
        list.remove(s);
     }
   }
desiredObject.setValue(list);

수정 후-

 List<String> list = new ArrayList<>();
 List<String> newList= new ArrayList<>();
 for (String s: list) {
   if(s is null or blank) {
      continue;
   }
   newList.add(s);
 }
 desiredObject.setValue(newList);

참고 URL : https://stackoverflow.com/questions/2965747/why-do-i-get-an-unsupportedoperationexception-when-trying-to-remove-an-element-f

반응형