Why do I get an UnsupportedOperationException when trying to remove an element from a List?

后端 未结 17 1965
后悔当初
后悔当初 2020-11-22 07:43

I have this code:

public static String SelectRandomFromTemplate(String template,int count) {
   String[] split = template.split(\"|\");
   List         


        
相关标签:
17条回答
  • 2020-11-22 07:55

    Quite a few problems with your code:

    On Arrays.asList returning a fixed-size list

    From the API:

    Arrays.asList: Returns a fixed-size list backed by the specified array.

    You can't add to it; you can't remove from it. You can't structurally modify the List.

    Fix

    Create a LinkedList, which supports faster remove.

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

    On split taking regex

    From the API:

    String.split(String regex): Splits this string around matches of the given regular expression.

    | is a regex metacharacter; if you want to split on a literal |, you must escape it to \|, which as a Java string literal is "\\|".

    Fix:

    template.split("\\|")
    

    On better algorithm

    Instead of calling remove one at a time with random indices, it's better to generate enough random numbers in the range, and then traversing the List once with a listIterator(), calling remove() at appropriate indices. There are questions on stackoverflow on how to generate random but distinct numbers in a given range.

    With this, your algorithm would be O(N).

    0 讨论(0)
  • 2020-11-22 07:55

    Creating a new list and populating valid values in new list worked for me.

    Code throwing error -

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

    After fix -

     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);
    
    0 讨论(0)
  • 2020-11-22 07:57

    Probably because you're working with unmodifiable wrapper.

    Change this line:

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

    to this line:

    List<String> list = new LinkedList<>(Arrays.asList(split));
    
    0 讨论(0)
  • 2020-11-22 07:59

    Following is snippet of code from Arrays

    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;
    

    so what happens is that when asList method is called then it returns list of its own private static class version which does not override add funcion from AbstractList to store element in array. So by default add method in abstract list throws exception.

    So it is not regular array list.

    0 讨论(0)
  • 2020-11-22 08:03

    This UnsupportedOperationException comes when you try to perform some operation on collection where its not allowed and in your case, When you call Arrays.asList it does not return a java.util.ArrayList. It returns a java.util.Arrays$ArrayList which is an immutable list. You cannot add to it and you cannot remove from it.

    0 讨论(0)
  • 2020-11-22 08:06

    I think that replacing:

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

    with

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

    resolves the problem.

    0 讨论(0)
提交回复
热议问题