137

I have an array I'd like to turn into a List, in order to modify the contents of the array.

Stack Overflow has plenty of questions/answers that address Arrays.asList() and how it only provides a List view of the underlying array, and how attempting to manipulate the resulting List will generally throw an UnsupportedOperationException as methods used to manipulate the list (e.g. add(), remove(), etc.) are not implemented by the List implementation provided by Arrays.asList().

But I can't find an example of how to turn an array into a mutable List. I suppose I can loop through the array and put() each value into a new List, but I'm wondering if there's an interface that exists to do this for me.

7 Answers 7

190

One simple way:

Foo[] array = ...;
List<Foo> list = new ArrayList<Foo>(Arrays.asList(array));

That will create a mutable list - but it will be a copy of the original array. Changing the list will not change the array. You can copy it back later, of course, using toArray.

If you want to create a mutable view onto an array, I believe you'll have to implement that yourself.

Sign up to request clarification or add additional context in comments.

7 Comments

Arrays.asList returns a view onto an array, with those mutating methods supported that don't affect the size of the list
@jon-skeet I know, I was just stating that Arrays.asList gives you an array backed list with limited mutability, if you need add/remove/insert then the ArrayList wrapping is a better approach.
Java needs to make mutability/immutability clear in all these static factory methods. It's a bummer to find out you made an immutable thing at runtime.
@dustinevan: The documentation is pretty clear IMO: "Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)"
@JonSkeet don't want to waste your time--thanks for all you do. I'd just like to put a vote in for more clarity in the names themselves--I'm sure the docs are clear. Some of us are dancing between languages, and this is reasonably clear in other languages.
|
48

And if you are using google collection API's (Guava):

Lists.newArrayList(myArray);

2 Comments

Even Guava itself recommends using either new ArrayList<>(Arrays.asList(...)) - the javadoc for the method implies it will become deprecated because it is not useful enough.
2020 and still not deprecated. Jump on in!
17

This simple code using the Stream API included in Java 8 creates a mutable list (or view) containing the elements of your array:

Foo[] array = ...;
List<Foo> list = Stream.of(array).collect(Collectors.toCollection(ArrayList::new));

Or, equally valid:

List<Foo> list = Arrays.stream(array).collect(Collectors.toCollection(ArrayList::new));

Comments

6

If you're using Eclipse Collections (formerly GS Collections), you can use FastList.newListWith(...) or FastList.wrapCopy(...).

Both methods take varargs, so you can create the array inline or pass in an existing array.

MutableList<Integer> list1 = FastList.newListWith(1, 2, 3, 4);

Integer[] array2 = {1, 2, 3, 4};
MutableList<Integer> list2 = FastList.newListWith(array2);

The difference between the two methods is whether or not the array gets copied. newListWith() doesn't copy the array and thus takes constant time. You should avoid using it if you know the array could be mutated elsewhere.

Integer[] array2 = {1, 2, 3, 4};
MutableList<Integer> list2 = FastList.newListWith(array2);
array2[1] = 5;
Assert.assertEquals(FastList.newListWith(1, 5, 3, 4), list2);

Integer[] array3 = {1, 2, 3, 4};
MutableList<Integer> list3 = FastList.wrapCopy(array3);
array3[1] = 5;
Assert.assertEquals(FastList.newListWith(1, 2, 3, 4), list3);

Note: I am a committer for Eclipse Collections.

1 Comment

That's a nice collections API you've got there. The first one I've seen that might tempt me away from my own implementations... only thing it seems to be missing that I find generally useful is a sorted set implementation backed by an array (which I find is much more efficient than a tree-based implementation for either data which is rarely modified or for sets that may be modified frequently but typically hold less than 10 or so elements).
3
myNewArrayList = new ArrayList<>(Arrays.asList(myArray));

4 Comments

@JonSkeet i know that your comment is from 2012, and i'm livin in the future now, but i'm assuming this comment hasn't held well considering my IDE specifically underlines and says "hey, don't declare this with a declared type. you don't need it there"?
@BrentThoenen: I don't understand your comment. Did you notice that my comment referred to revision 1, which used myNewArrayList = new ArrayList(...), i.e. the raw type? There's a difference between "using the diamond operator to let the compiler work out a type argument" and "using a raw type".
I posted this answer and lived in oblivion all this time that @JonSkeet Himself commented on my answer. Thanks Brent for commenting.
@JonSkeet ahh, my bad. i didn't check the revision you were commenting on. I made a wrong assumption in that 2012 java assumed empty diamond operator as a raw type as well. That is my b. thanks for the answer!
0

As an alternative, you can pass a simple statement during the constructor call of ArrayList:

myNewArrayList = new ArrayList<>({
    addAll(Arrays.asList(myArray));
});

3 Comments

I do not understand that code. On what object are you calling addAll? Can you show working code on a demo site such as Ideone.com?
Yes, or simply myNewArrayList = new ArrayList<>(Arrays.asList(myArray));
@BasilBourque I am calling addAll from the constructor call.
0

tl;dr

new ArrayList <> ( List.of ( arr ) )

List.of

In Java 9+, you can:

  1. Pass an array to List.of to create an unmodifiable List collection.
  2. Then pass that resulting list to the constructor of a modifiable List implementation such as ArrayList or LinkedList.

The List.of Javadoc explains:

This method also accepts a single array as an argument. The element type of the resulting list will be the component type of the array, and the size of the list will be equal to the length of the array.

String[] arr = { "x" , "y" , "z" } ;
List < String > unmodifiableList = List.of ( arr ) ;
List < String > modifiableList = new ArrayList <> ( unmodifiableList ) ;

More briefly:

List < String > list = new ArrayList <> ( List.of ( arr ) ) ;

See this code run at Ideone.com.

Arrays.toString ( arr ) = [x, y, z]
unmodifiableList.toString() = [x, y, z]
modifiableList.toString() = [x, y, z]
list.toString() = [x, y, z]

This approach is inefficient because we instantiate one list only to populate another list. Nevertheless, for small amounts of data under occasional use, the brevity and clarity of the code may outweigh the slight inefficiency.

Comments

Your Answer

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.