Why Do I Get an Unsupportedoperationexception When Trying to Remove an Element from a List

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

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

UnsupportedOperationException when trying to remove a list of items from another list

Arrays.asList returns Arrays.ArrayList, a List implementation that doesnt support the removal of elements. Use

List<Integer> validDates = new ArrayList<>(Arrays.asList(26,27,28,1,2,3,4));

Why does List.remove(int) throw java.lang.UnsupportedOperationException?

You're using it on a List implementation returned by Arrays.asList(), which returns a fixed-length collection, therefore a remove is unsupported.

UnsupportedOperationException when trying to remove from the list returned by Array.asList

Array.asList() wraps an array in the list interface. The list is still backed by the array. Arrays are a fixed size - they don't support adding or removing elements, so the wrapper can't either.

The docs don't make this as clear as they might, but they do say:

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

The "fixed-size" bit should be a hint that you can't add or remove elements :)

Although there are other ways around this (other ways to create a new ArrayList from an array) without extra libraries, I'd personally recommend getting hold of the Google Collections Library (or Guava, when it's released). You can then use:

List<Integer> list = Lists.newArrayList(array);

The reason I'm suggesting this is that the GCL is a generally good thing, and well worth using.

As noted in comments, this takes a copy of the array; the list is not backed by the original array, and changes in either collection will not be seen in the other.

Remove item in arrayList , java.lang.UnsupportedOperationException

Change

List<String> historylist = Arrays.asList(history);

to

 List<String> historylist = new LinkedList (Arrays.asList(history));

and see this post why this error occur in case of List :

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

why do i get an unsupported operation exception when i want to remove an object from a treeset

List.copyOf

This makes an immutable (i.e.: Read Only) copy of whatever you pass to it. There is no further point in making copies of this (and, in fact, I believe if you pass an already-immutable list in there it just returns it verbatim; no point making copies of things that cannot be modified).

When creating a DominoPile object, you pass the result of List.copyOf to its constructor, meaning, the pile field in DominoPile is now one of these immutable lists. A while later your code invokes getOutLastOne which modifies (mutates) the list referenced by the pile field, which doesn't work, because it cannot be modified. As the exception states.

That's the problem. There are 3 different strategies you can use to fix the problem. In broad strokes:

  1. Document in the constructor of DominoPile that the passed-in list is taken verbatim and will be modified as is, meaning: It must not be immutable (it's now the duty of the caller to read the docs and do what it says), and any effects caused on the list by DominoPile (such as removing the last one) echo through to the list used to create the DominoPile object in the first place.

Once you've done that (basically, all you need to do is, add some javadoc), then the caller (where you currently have new DominoPile(List.copyOf(kg....))) needs to stop passing immutable list. This is easy enough - replace List.copyOf(X) with new ArrayList<>(X) - that also makes a copy, but a mutable one.


  1. Alternatively, you can also choose a slightly different design: Have DominoPile treat the provided list merely as a template, and thus have your DominoPile constructor make a new (mutable!) list that is a copy of it. In other words, replace this.pile = pile, both in the constructor and the set method, with this.pile = new ArrayList<>(pile) instead. But I kinda dislike the name setPile if that's what happens.

  2. DominoPile becomes immutable, all set methods need to go away, all data structures become immutable, and a method like .getOutLastOne doesn't actually remove anything (it can't - everything cannot be modified), instead it makes an entirely new DominoPile object that is a clone of itself, except with one domino removed. Now the fact that your lists are immutable is, if anything, a benefit. This is... over-engineering things by quite a large margin, I think.

The options are listed in order of how I'd do it - so, unless you have a pressing reason why the first option sounds bad to you, I'd just go with the first, here. Based on your API design (such as having a set method, meaning you do not appear to particularly desire immutability).

Getting UnsupportedOperationException when i remove elements at particular index in List<List<String>>?

Though I dont have enough information available, I suspect that the list returned is probably fixed size (or unmodifiable in some other way). One example is the list we get from Arrays.asList to which cannot add/remove anything.We can't structurally modify this List.

The solution may be to initialize a list implementation using the items in current list. A LinkedList supports faster remove and may be suitable. Something like:

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

You can also use ArrayList if it suits your requirement.

UnsupportedOperationException when using iterator.remove()

Arrays.asList() returns a list, backed by the original array. Changes you make to the list are also reflected in the array you pass in. Because you cannot add or remove elements to arrays, that is also impossible to do to lists, created this way, and that is why your remove call fails.
You need a different implementation of List (ArrayList, LinkedList, etc.) if you want to be able to add and remove elements to it dynamically.



Related Topics



Leave a reply



Submit