155

Is there an advantage (or much of a difference) to using Arrays.asList(something) over Collections.singletonList(something) to make a list containing one item? The latter makes the returned list immutable as well.

user2864740
  • 54,112
  • 10
  • 112
  • 187
Howard Grimberg
  • 1,918
  • 2
  • 15
  • 25

3 Answers3

224

Collections.singletonList(something) is immutable whereas Arrays.asList(something) is a fixed size List representation of an Array where the List and Array gets joined in the heap.

Arrays.asList(something) allows non-structural changes made to it, which gets reflected to both the List and the conjoined array. It throws UnsupportedOperationException for adding, removing elements although you can set an element for a particular index.

Any changes made to the List returned by Collections.singletonList(something) will result in UnsupportedOperationException.

Also, the capacity of the List returned by Collections.singletonList(something) will always be 1 unlike Arrays.asList(something) whose capacity will be the size of the backed array.

Kumar Abhinav
  • 6,274
  • 2
  • 19
  • 32
  • 3
    For some reason the IDE (Android Studio) tells me I should use `Collections.singletonList` instead. Could it really know that it's safe to use it? You write (and according to my tests, it's true) that it could cause an exception if it's being modified (set/remove, for example)... – android developer Aug 19 '20 at 07:53
65

I would just add that the singletonlist is not backed by an array and just has a reference to that one item. Presumably, it would take less memory and can be significant depending on the number of lists you want to create.

apprentice
  • 801
  • 5
  • 6
  • Any link or code to back this memory efficiency point ? I have this Arrays.asList(ONLY_ONE_OBJECT) written vastly across a codebase and would like to find out if replacing with Collections.singletonList() leads to memory efficiency? – Rahul Saini Oct 01 '19 at 11:49
  • Arrays.asList references an array (obviously): http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/be44bff34df4/src/share/classes/java/util/Arrays.java#l3810 Collections.singletonList: http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/be44bff34df4/src/share/classes/java/util/Collections.java#l4801 – Benjamin Jun 30 '20 at 08:25
15

The method Arrays.asList returns a fixed-size list backed by the specified array. The method returns an instance of ArrayList which is a private nested static class extending AbstractList and not java.util.ArrayList. This static class provides implementation of few methods e.g. set, indexOf, forEach, replaceAll etc. but when we invoke add it has no implementation of its own, rather method from AbstractList is invoked which throws java.lang.UnsupportedOperationException.

The Collections.singletonList returns an immutable list containing only the specified object and it is serializable as well.

On a side note, for immutable lists we generally use Collections.unmodifiableList which returns an unmodifiable view of the specified list.

List<String> srcList = Arrays.asList("Apple", "Mango", "Banana");
var fruits = new ArrayList<>(srcList);
var unmodifiableList = Collections.unmodifiableList(fruits);     
fruits.set(0, "Apricot");
var modFruit = unmodifiableList.get(0);
System.out.println(modFruit); // prints Apricot

An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view.

We can have a true immutable list in Java 10 and later. There are two ways to get truly unmodifiable list:

  1. var unmodifiableList = List.copyOf(srcList);
  2. var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList()); If any of these two variables are used value will still be "Apple" and not "Apricot".

As per doc of Java 10:

The List.of and List.copyOf static factory methods provide a convenient way to create unmodifiable lists. The List instances created by these methods have the following characteristics:

  1. They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List's contents to appear to change.
  2. They disallow null elements. Attempts to create them with null elements result in NullPointerException.
  3. They are serializable if all elements are serializable.
  4. The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
  5. They are value-based. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided.
  6. They are serialized as specified on the Serialized Form page.
akhil_mittal
  • 18,855
  • 7
  • 83
  • 82