124

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.

Mifeet
  • 12,949
  • 5
  • 60
  • 108
ericsoco
  • 24,913
  • 29
  • 97
  • 127

5 Answers5

170

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This is completely acceptable for my needs. I'm fine with discarding the original array. – ericsoco Jul 25 '12 at 23:53
  • 3
    Arrays.asList returns a view onto an array, with those mutating methods supported that don't affect the size of the list – Timo Westkämper Dec 11 '12 at 08:03
  • @TimoWestkämper: Yes, but I'm then creating a new `ArrayList` from that view. – Jon Skeet Dec 11 '12 at 08:49
  • 1
    @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. – Timo Westkämper Dec 11 '12 at 09:10
  • 4
    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 Jun 19 '18 at 07:26
  • 2
    @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.)" – Jon Skeet Jun 19 '18 at 08:44
  • 1
    @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. – dustinevan Jun 19 '18 at 20:20
44

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

Lists.newArrayList(myArray);
catch23
  • 17,519
  • 42
  • 144
  • 217
vsingh
  • 6,365
  • 3
  • 53
  • 57
15

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));
MikaelF
  • 3,518
  • 4
  • 20
  • 33
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.

Donald Raab
  • 6,458
  • 2
  • 36
  • 44
Craig P. Motlin
  • 26,452
  • 17
  • 99
  • 126
  • 1
    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). – Jules Mar 13 '14 at 07:12
2
myNewArrayList = new ArrayList<>(Arrays.asList(myArray));
Lezorte
  • 473
  • 1
  • 5
  • 13
Sid
  • 4,893
  • 14
  • 55
  • 110
  • 1
    @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"? – Brent Thoenen Jul 24 '19 at 14:50
  • 1
    @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". – Jon Skeet Jul 24 '19 at 15:46
  • 1
    I posted this answer and lived in oblivion all this time that @JonSkeet Himself commented on my answer. Thanks Brent for commenting. – Sid Jul 24 '19 at 17:09
  • 1
    @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! – Brent Thoenen Jul 25 '19 at 16:04