Arrays.asList()vs Collections.singletonList()

时间:2014-09-24 22:10:47

标签: java collections

在Collections.singletonList(something)上使用Arrays.asList(something)制作包含一个项目的列表是否有优势(或许多不同之处)?后者使得返回的列表也是不可变的。

3 个答案:

答案 0 :(得分:168)

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

Arrays.asList(something)允许对其进行非结构性更改,它会反映到List和连接数组中。虽然您可以为特定索引设置元素,但它会抛出 UnsupportedOperationException 来添加,删除元素。

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

此外,Collections.singletonList(something)返回的列表容量将始终 1 ,而Arrays.asList(something)的容量将是已支持数组的大小。

答案 1 :(得分:57)

我只想补充说,singletonlist没有数组支持,只是引用了那个项目。据推测,它会占用更少的内存,并且可能很重要,具体取决于您要创建的列表数量。

答案 2 :(得分:7)

方法Arrays.asList返回由指定数组支持的固定大小的列表。该方法返回ArrayList的实例,它是扩展了AbstractList而不是java.util.ArrayList私有嵌套静态类。该静态类提供了几种方法的实现,例如set, indexOf, forEach, replaceAll等,但是当我们调用add时,它没有自己的实现,而是调用了AbstractList中的方法,该方法抛出了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()); =>打印苹果

根据 Java 10 doc

  

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

     
      
  1. 他们是unmodifiable。元素无法添加,删除或替换。调用List上的任何mutator方法总是会导致   UnsupportedOperationException被抛出。但是,如果包含   元素本身是可变的,这可能导致列表的内容   似乎改变了。
  2.   
  3. 它们不允许使用null元素。尝试使用空元素创建它们会导致NullPointerException
  4.   
  5. 如果所有元素都是可序列化的,则它们是可序列化的。
  6.   
  7. 列表中元素的顺序与提供的参数或数组中的元素的顺序相同。
  8.   
  9. 他们是value-based。调用者不应对返回实例的身份做任何假设。工厂可以自由创建新的   实例或重用现有实例。因此,身份敏感   这些实例上的操作(引用相等(==),标识哈希   代码和同步)是不可靠的,应避免使用。
  10.   
  11. 它们已按照Serialized Form页上的指定进行了序列化。
  12.