299

I try to add objects to a List<String> instance but it throws an UnsupportedOperationException. Does anyone know why?

My Java code:

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

The error message:

java.lang.UnsupportedOperationException
 java.util.AbstractList.add(Unknown Source)
 java.util.AbstractList.add(Unknown Source)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Matthias Braun
34.7k27 gold badges158 silver badges177 bronze badges
asked Apr 22, 2011 at 12:39
0

9 Answers 9

569

Not every List implementation supports the add() method.

One common example is the List returned by Arrays.asList(): it is documented not to support any structural modification (i.e. removing or adding elements) (emphasis mine):

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

Even if that's not the specific List you're trying to modify, the answer still applies to other List implementations that are either immutable or only allow some selected changes.

You can find out about this by reading the documentation of UnsupportedOperationException and List.add(), which documents this to be an "(optional operation)". The precise meaning of this phrase is explained at the top of the List documentation.

As a workaround you can create a copy of the list to a known-modifiable implementation like ArrayList:

seeAlso = new ArrayList<>(seeAlso);
answered Apr 22, 2011 at 12:43
4
  • 1
    so i have to use the list instance to test if it contain my element and the array instance when i have to add an element? that's write? Commented Apr 22, 2011 at 12:56
  • 110
    @Florito: This will work though: List<String> listMembres = new ArrayList<String>(Arrays.asList(tabMembres)); :) Commented Apr 22, 2011 at 12:56
  • or maybe i have to cast my List object to ArrayList or another? Commented Apr 22, 2011 at 12:57
  • 2
    No, not really. If you want to add an element to a List implementation that doesn't allow addition, then you'll have to copy that List to an implementation that does (ArrayList is a common candidate) and add to that. Commented Apr 22, 2011 at 12:58
13

Many of the List implementation support limited support to add/remove, and Arrays.asList(membersArray) is one of that. You need to insert the record in java.util.ArrayList or use the below approach to convert into ArrayList.

With the minimal change in your code, you can do below to convert a list to ArrayList. The first solution is having a minimum change in your solution, but the second one is more optimized, I guess.

 String[] membersArray = request.getParameterValues('members');
 ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));

OR

 String[] membersArray = request.getParameterValues('members');
 ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));
answered Nov 23, 2018 at 12:46
0
5

Form the Inheritance concept, If some perticular method is not available in the current class it will search for that method in super classes. If available it executes.

It executes AbstractList<E> class add() method which throws UnsupportedOperationException.


When you are converting from an Array to a Collection Obejct. i.e., array-based to collection-based API then it is going to provide you fixed-size collection object, because Array's behaviour is of Fixed size.

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

Souce samples for conformation.

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> {
 //...
 }
}

Form the above Source you may observe that java.util.Arrays.ArrayList class doesn't @Override add(index, element), set(index, element), remove(index). So, From inheritance it executes super AbstractList<E> class add() function which throws UnsupportedOperationException.

As AbstractList<E> is an abstract class it provides the implementation to iterator() and listIterator(). So, that we can iterate over the list object.

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

You can even create Fixed-Size array form Collections class Collections.unmodifiableList(list);

Sample Source:

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 — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data.

@see also

answered Dec 12, 2018 at 8:20
3

You will also get this exception if you attempt to add to a List<T> returned by Collections.singletonList(T o):

Returns an immutable list containing only the specified object. The returned list is serializable.

The JVM does not implement add() for Collections.singletonList

dbc
119k27 gold badges270 silver badges399 bronze badges
answered Mar 15, 2021 at 16:48
0
2

List membersList = Arrays.asList(membersArray);

returns immutable list, what you need to do is

new ArrayList<>(Arrays.asList(membersArray)); to make it mutable

answered Oct 23, 2018 at 5:45
1
  • It is not an immutable list. Mutation operations that don't change the list length are supported / will work. The key thing is that the list's length cannot change because the list is backed by an array ... whose length can't change. Commented Mar 17, 2019 at 0:33
0

You must initialize your List seeAlso :

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

or

List<String> seeAlso = new ArrayList<String>();
kleopatra
51.6k28 gold badges102 silver badges218 bronze badges
answered Feb 28, 2013 at 9:35
1
  • 3
    An uninitialized variable won't cause UnsupportedOperationException in add(). You would get an NPE instead. Commented Mar 17, 2019 at 0:31
0

The reason for the UnsupportedOperationException is because the Arrays.asList() method returns a fixed-size list backed by the original array. This means that you cannot modify the size of the list by adding or removing elements, and attempting to do so will result in an UnsupportedOperationException.

answered Apr 27, 2023 at 19:43
-3

You cannot modify a result from a LDAP query. Your problem is in this line:

seeAlso.add(groupDn);

The seeAlso list is unmodifiable.

answered Apr 22, 2011 at 12:43
1
  • 1
    the problem is not due to that but as Joachim pointed out above it is to do with implementations of List that might not support add(). Commented Apr 22, 2011 at 12:48
-4

instead of using add() we can use addall()

{ seeAlso.addall(groupDn); }

add adds a single item, while addAll adds each item from the collection one by one. In the end, both methods return true if the collection has been modified. In case of ArrayList this is trivial, because the collection is always modified, but other collections, such as Set, may return false if items being added are already there.

answered Jun 17, 2019 at 12:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.