Arrays.asList()与Collections.singletonList()


136

使用Arrays.asList(something)优于Collections.singletonList(something)来构成包含一项的列表是否有优势(或有很大不同)?后者使返回的列表也不可变。


8
您也可以将番石榴ImmutableList.of()Lists.newArrayList()其他混合在一起。
biziclop 2014年

除此之外,当方法返回一个列表,该列表后来被下游修改时,我遇到了Collections.singletonList()引起的问题。
霍华德·格里姆贝格

1
Java 10具有真正的不可变列表:stackoverflow.com/a/52536126/1216775
akhil_mittal,

Answers:


205

Collections.singletonList(something)不可变的,而数组Arrays.asList(something)是固定大小的List表示形式,列表和数组在堆中连接在一起。

Arrays.asList(something)允许对其进行非结构性更改,这些更改会同时反映到List和联合数组中。UnsupportedOperationException尽管您可以为特定索引设置元素,但它会添加,删除元素。

对返回的列表所做的任何更改Collections.singletonList(something)都会导致UnsupportedOperationException

同样,返回的列表的容量Collections.singletonList(something)将始终为1,这Arrays.asList(something)与其后备阵列的容量不同。


63

我只想补充一点,单例列表不由数组支持,而仅具有对该项的引用。据推测,这将占用较少的内存,并且可能很重要,具体取决于您要创建的列表的数量。


是否有任何链接或代码支持此内存效率点?我已经将此Arrays.asList(ONLY_ONE_OBJECT)广泛地写在整个代码库中,想知道是否用Collections.singletonList()替换会导致内存效率提高?
拉胡尔·塞尼


12

该方法Arrays.asList返回由指定数组支持的固定大小的列表。该方法返回一个实例,ArrayList该实例是一个扩展的私有嵌套静态类AbstractList而不是java.util.ArrayList。这个静态类提供了一些方法的实现,例如set, indexOf, forEach, replaceAlletc等,但是当我们调用add它时,它没有自己的实现,而是AbstractList调用了throw引发的方法java.lang.UnsupportedOperationException

所述Collections.singletonList返回一个不可变列表仅包含指定的对象,这是可序列化的为好。

附带说明一下,对于不可变列表,我们通常使用Collections.unmodifiableList它返回指定列表的不可修改视图。

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

不可修改的视图集合是不可修改的集合,并且也是支持集合的视图。请注意,对后备集合的更改仍然可能发生,并且如果发生更改,则可以通过不可修改的视图看到它们。

Java 10及更高版本中,我们可以有一个真正的不可变列表。有两种方法可以获取真正不可修改的列表

  1. var unmodifiableList = List.copyOf(srcList);
  2. var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList()); 如果使用这两个变量中的任何一个,则值仍将是“ Apple”而不是“ Apricot”。

按照文档Java的10

List.ofList.copyOf静态工厂方法提供了一种方便的方式来创建不可修改的列表。这些方法创建的List实例具有以下特征:

  1. 它们是不可修改的。元素无法添加,删除或替换。调用List上的任何mutator方法总是会导致 UnsupportedOperationException抛出该异常。但是,如果所包含的元素本身是可变的,则可能导致列表的内容似乎发生变化。
  2. 它们不允许使用null元素。尝试使用null元素创建它们会导致NullPointerException
  3. 如果所有元素都是可序列化的,则它们是可序列化的。
  4. 列表中元素的顺序与提供的参数或提供的数组中的元素的顺序相同。
  5. 他们是value-based。调用者不应对返回实例的身份做任何假设。工厂可以自由创建新实例或重用现有实例。因此,在这些实例上的身份敏感操作(引用相等(==),身份哈希码和同步)不可靠,应避免。
  6. 它们按照“ 序列化表格”页面上的指定进行序列化
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.