This question already has answers here:
UnsupportedOperationException when trying to remove from the list returned by Array.asList
(6 answers)
Closed 3 years ago.
I have next code:
List<String> str=Arrays.asList("cat","tiger","dog","mouse");
str.add("horse");
It compiles, but at runtime I have UnsupportedOperationException. Why does it happen?
Arrays.asList(String...) creates an unmodifiable array. Wrap it with another ArrayList like so:
List<String> str = new ArrayList<>(Arrays.asList("cat","tiger","dog","mouse"));
str.add("horse");
this called backed list .
backed list it's created when you convert an array to list but keep in your mind the element in the array is linked with the element in the list so you cant add or delete any thing and you are using varargs its similar to array ,
Arrays.asList() returns a list that is fixed-size and backed by the array you pass so you can't add or remove elements because that would mean changing the array as well. (note that if you have a look at the source you'll find that Arrays.asList() will return an instance of java.util.Arrays.ArrayList which you should not confuse with java.util.ArrayList which you probably already know).
Instead you'd need to create another list, e.g via calling new ArrayList<String>( Arrays.asList(...)) which effectively makes a copy of the passed list.
A Java 8+ way might be this:
List<String> str = Stream.of( "cat","tiger","dog","mouse" ).collect( Collectors.toList() );
Related
This question already has answers here:
Polymorphism: Why use "List list = new ArrayList" instead of "ArrayList list = new ArrayList"? [duplicate]
(8 answers)
Closed 5 years ago.
Which one is better and why ?
a) List<String> list = new ArrayList<>();
b) ArrayList<String> list = new ArrayList<>();
It depends on the context.
If you care only about the list semantics and not for the particular implementation, go for List<String>. If you want to enforce a particular implementation, go for ArrayList<String>, LinkedList<String> or anything else.
In most cases, you will want to go on with the interface and not the particular implementation.
(a) is better because it is more flexible. If for example, suddenly your requirement changes and says "Instead of creating a new empty array list to assign to the variable list, we will populate the list with items filtered from another list", you need to change your code for that. You might change it to something like this:
List<String> list = anotherList.stream().filter(x -> x.length() > 2).collect(Collectors.toList());
Since collect(Collectors.toList()) returns a List, you also need to change the type of list if you were using the code in (b).
Another situation is that later on you found out that you need to assign some other kind of list e.g. LinkedList to list. If you were using the code in (a), you can just assign the linked list straight away. If you were using the code in (b), you will have to go back to the declaration of list and change the type.
The general pattern is that as you use more "abstract" types, your code becomes more flexible but at the same time you can do less with your variables. For example, you can't use methods declared only in ArrayList on your list variable, but on the other hand, other kinds of lists can be assigned to list. If you an even more abstract type, Collection, then you can't use the members only declared in List anymore, but then all kinds of collections - Set, Map etc - can be assigned.
This question already has answers here:
Why does Arrays.asList() return its own ArrayList implementation
(6 answers)
Closed 5 years ago.
Referring to Difference between Arrays.asList(array) vs new ArrayList<Integer>(Arrays.asList(ia)) in java
I was curious as in what's the exact purpose of Arrays.asList() method.
When we create a new List from it, say for example -
Integer[] I = new Integer[] { new Integer(1), new Integer(2), new Integer(3) };
List<Integer> list1 = Arrays.asList(I);
List<Integer> list2 = ((List<Integer>) Arrays.asList(I));
We cannot perform most of the the regular operations on it like .add(), .remove(). Thus, I was not able add an iterator to it to avoid concurrent modification.
Oracle docs state
public static List asList(T... a)
Returns a fixed-size list backed by the specified array. (Changes to
the returned list "write through" to the array.) This method acts as
bridge between array-based and collection-based APIs, in combination
with Collection.toArray(). The returned list is serializable and
implements RandomAccess.
It works well with creating a new List. List<Integer> list3 = new ArrayList<>(Arrays.asList(I));
So, why this and what are its advantages and disadvantages?
Not being able to call add, remove, etc is the exact difference. If you don't need those methods, Arrays.asList gives you a perfectly fine view of the array as a List (for APIs that take collections rather than arrays). If you need to change the "shape" of the list, then new ArrayList<>(Arrays.asList(myArray)) is the way to go.
This question already has answers here:
Java List.add() UnsupportedOperationException
(8 answers)
Closed 3 years ago.
List.addAll throwing UnsupportedOperationException when trying to add another list.
List<String> supportedTypes = Arrays.asList("6500", "7600"};
and in loop I am doing,
supportedTypes.addAll(Arrays.asList(supportTypes.split(","))); //line 2
reading supportTypes from a file.
But line 2 throws a UnsupportedOperationException, but I am not able to determine why?
I am adding another list to a list, then why this operation is unsupported?
Arrays.asList returns a fixed sized list backed by an array, and you can't add elements to it.
You can create a modifiable list to make addAll work :
List<String> supportedTypes = new ArrayList<String>(Arrays.asList("6500", "7600", "8700"));
This error also happens when the list is initialized with Collections.emptyList(), which is immutable:
List<String> myList = Collections.emptyList();
Instead, initialize it with a mutable list. For example
List<String> myList = new ArrayList<>();
Arrays.asList returns a fixed-size list.
If you to want be able to add elements to the list, do:
List<String> supportedTypes = new ArrayList<>(Arrays.asList("6500", "7600"});
supportedTypes.addAll(Arrays.asList(supportTypes.split(",")));
Problem is that Arrays.asList method returns instance of java.util.Arrays.ArrayList which doesn't support add/remove operations on elements. It's not surprizing that addAll method throws exception because add method for java.util.Arrays.ArrayList is defined as:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
Related question:
Arrays.asList() Confusing source code
From the documentation:
Arrays.asList returns a fixed-size list backed by the specified array.
In my case this exception occured when I called adapter.addAll(items), where adapter was a custom ArrayAdapter. This CustomAdapter had a parameter of type Array instead of ArrayList.
This question already has answers here:
Initialization of an ArrayList in one line
(34 answers)
Closed 6 years ago.
Is there a Utility method somewhere that can do this in 1 line? I can't find it anywhere in Collections, or List.
public List<String> stringToOneElementList(String s) {
List<String> list = new ArrayList<String>();
list.add(s);
return list;
}
I don't want to re-invent the wheel unless I plan on putting fancy rims on it.
Well... the type can be T, and not String. but you get the point. (with all the null checking, safety checks...etc)
Fixed size List
The easiest way, that I know of, is to create a fixed-size single element List with Arrays.asList(T...) like
// Returns a List backed by a varargs T.
return Arrays.asList(s);
Variable size List
If it needs vary in size you can construct an ArrayList and the fixed-sizeList like
return new ArrayList<String>(Arrays.asList(s));
and (in Java 7+) you can use the diamond operator <> to make it
return new ArrayList<>(Arrays.asList(s));
Single Element List
Collections can return a list with a single element with list being immutable:
Collections.singletonList(s)
The benefit here is IDEs code analysis doesn't warn about single element asList(..) calls.
Collections.singletonList(object)
the list created by this method is immutable.
You can use the utility method Arrays.asList and feed that result into a new ArrayList.
List<String> list = new ArrayList<String>(Arrays.asList(s));
Other options:
List<String> list = new ArrayList<String>(Collections.nCopies(1, s));
and
List<String> list = new ArrayList<String>(Collections.singletonList(s));
ArrayList(Collection) constructor.
Arrays.asList method.
Collections.nCopies method.
Collections.singletonList method.
With Java 7+, you may use the "diamond operator", replacing new ArrayList<String>(...) with new ArrayList<>(...).
Java 9
If you're using Java 9+, you can use the List.of method:
List<String> list = new ArrayList<>(List.of(s));
Regardless of the use of each option above, you may choose not to use the new ArrayList<>() wrapper if you don't need your list to be mutable.
With Java 8 Streams:
Stream.of(object).collect(Collectors.toList())
or if you need a set:
Stream.of(object).collect(Collectors.toSet())
The other answers all use Arrays.asList(), which returns an unmodifiable list (an UnsupportedOperationException is thrown if you try to add or remove an element). To get a mutable list you can wrap the returned list in a new ArrayList as a couple of answers point out, but a cleaner solution is to use Guava's Lists.newArrayList() (available since at least Guava 10, released in 2011).
For example:
Lists.newArrayList("Blargle!");
Very simply:
Arrays.asList("Hi!")
Seeing as Guava gets a mention, I thought I would also suggest Eclipse Collections (formerly known as GS Collections).
The following examples all return a List with a single item.
Lists.mutable.of("Just one item");
Lists.mutable.with("Or use with");
Lists.immutable.of("Maybe it must be immutable?");
Lists.immutable.with("And use with if you want");
There are similar methods for other collections.
Yet another alternative is double brace initialization, e.g.
new ArrayList<String>() {{ add(s); }};
but it is inefficient and obscure. Therefore only suitable:
in code that doesn't mind memory leaks, such as most unit tests and other short-lived programs;
and if none of the other solutions apply, which I think implies you've scrolled all the way down here looking to populate a different type of container than the ArrayList in the question.
This question already has answers here:
Java Convert Object[] Array to Vector
(6 answers)
Closed 9 years ago.
Do I have to push my elements one by one? I tried something like
String[] array;
array=...
Vector<String> vector = new Vector<String>(array);
but my eclipse marks this as an error.
Vector doesn't have a constructor that accepts an array directly.
Assuming that array is of type String[], you could do
Vector<String> vector = new Vector<String>(Arrays.asList(array));
Better to use ArrayList as it doesn't have the overhead of having synchronized methods. You could use
List<String> list = new ArrayList<>(Arrays.asList(array));
This will produce a mutable collection also.
That can't work, since, as the documentation shows, there is no Vector constructor taking an array as argument.
If you just want a non-modifiable list, use
List<String> list = Arrays.asList(array);
If you really want a Vector (but you should use ArrayList instead, because Vector is obsolete), use
Vector<String> vector = new Vector<String>(Arrays.asList(array));
I'm not 100% sure what you mean by 'one by one'. If you want to add an existing collection to a Vector, you could use this.
If you want to do it one by one, you need to iterate through the items, and call Vector's 'add' method.
for(String item: array) {
vector.add(item);
}