使用Arrays.asList的优点和缺点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Arrays.asList的优点和缺点相关的知识,希望对你有一定的参考价值。

我想知道使用Arrays.asList的利弊。我在代码中使用它时遇到了问题。

另外,我想知道在不使用Arrays.asList的情况下将数组转换为数组列表(集合)的最佳方法

答案

要将数组转换为ArrayList,我会这样做:

new ArrayList<T>(Arrays.asList(myArray));

您需要将列表包装在新的ArrayList中,否则您将无法添加任何元素,因为asList()返回的列表具有固定大小。因此,在尝试添加元素时会出现UnsupportedOperationException。

但是如果你不喜欢上面的方法,你可能也想这样做:

Collections.addAll(arraylist, array);

据我所知,两者在性能方面都是相同的。


但更重要的是,使用第一种方法有什么问题?

另一答案

我想知道使用Arrays.asList的优缺点。

主要的“专业人士”是:

  • 它不涉及复制数据,
  • 您的列表将看到支持数组中所做的任何更改(如果您需要)

主要的“缺点”是:

  • 你不能通过“asList”包装器添加或删除元素,
  • 您的列表将看到对支持数组所做的任何更改(如果您不希望这样)

(还有一个明显的局限性:你不能将asList应用于基元数组。但是转换基元数组无论如何都是非常重要的......)


我想知道在不使用Arrays.asList的情况下将数组转换为数组列表(集合)的最佳方法

在不使用aslist的情况下将数组转换为列表的最简单方法是:

new ArrayList<T>(Arrays.asList(arrayOfT))

你可以通过以下方式获得更好的性能:

ArrayList<T> list = new ArrayList<T>(arrayOfT.length);
Collections.addAll(list, arrayOfT);

因为ArrayList<T>(Collection<T>)构造函数首先调用toArray()来创建一个临时数组(至少在Java 7中它是这样)。这意味着引擎盖下会有一个额外的副本。

但最重要的是,使用Arrays.asList比避免使用它更简单,更便宜。

另一答案

Arrays.asList允许您查看数组,就像它是List一样。这意味着将来对阵列的更改将影响List,并且对List的未来更改会影响该阵列。这是好事还是坏事取决于你打算用List做什么,以及你希望它如何与数组相关。

对于丢弃使用我绝对会使用Arrays.asList。例如,List有一个显示内容的toString,因此System.out.println(Arrays.asList(myArray))可能很有用。

如果你想保留数组的快照,不受未来更改的影响,我仍然会使用Arrays.asList,但是从结果中创建一个新的List,如@NNzz的上一个答案所示。

另一答案

除了现有的答案,特别是@Stephen C的一个很好的答案,Arrays.asList还有一个问题。

来自Effective Java


Arrays.asList从来没有被设计为将多个参数收集到一个列表中,但是当将varargs添加到平台时,改进它以进行更改似乎是个好主意。结果,可以做这样的事情:

List<String> homophones = Arrays.asList("to", ""too", "two");

这种用法有效,但启用它是一个很大的错误。

在1.5版之前,这是打印数组内容的常用习惯用法:

// Obsolete idiom to print an array!
System.out.println(Arrays.asList(myArray));

这个成语是必要的,因为数组从Object继承了它们的toString实现,因此直接在数组上调用toString会产生一个无用的字符串,如[Ljava.lang.Integer;@3e25a5。这个成语只适用于对象引用类型的数组,但是如果你不小心在一个基元数组上尝试它,程序将无法编译。例如,这个程序:

public static void main(String[] args) {
    int[] digits = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };
    System.out.println(Arrays.asList(digits));
}

将在1.4版中生成此错误消息:

Va.java:6:Arrays中的asList(Object [])不能应用于(int [])System.out.println(Arrays.asList(digits));

由于不幸的决定在1.5版本中将Arrays.asList改进为varargs方法,因此该程序现在编译时没有错误或警告。

从好的方面来看,用于将数组转换为字符串的Arrays.asList成语现在已经过时,而且目前的习惯用语要强得多。同样在1.5版本中,Arrays类被赋予了完整的Arrays.toString方法(不是varargs方法!),专门用于将任何类型的数组转换为字符串。如果你使用Arrays.toString代替Arrays.asList,程序会产生预期的结果:

// The right way to print an array
System.out.println(Arrays.toString(myArray));
另一答案

从Java 8开始,我认为创建新Array的最简单有效的方法是:

Stream.of(myArray).collect(Collectors.toList());

更好的不再使用

new ArrayList<>(Arrays.asList());

由于这是2次工作,这会影响内存/性能下降

关于Arrays.asList,我想几乎所有人都已经清楚地解释过了。我想为使用Arrays.asList添加更多的不良体验。这已经很久以前了,所以在这一点上可能与某些部分无关。

在几年前的一个项目中,我总是使用Arrays.asList,因为它更简单,更清晰的列表初始化。然后我做的是将arrayList传递给另一个方法甚至库。问题是某些库将Arrays.ArrayList视为ArrayList。因此,当它试图强制转换为java.util.ArrayList时,它将导致问题

List<String> arrayList = Arrays.asList(x);
ArrayList<String> arr = (ArrayList) arrayList; //this will cause error
  • 某些映射器(例如:dozer)之前无法读取Arrays.asList的方法签名,因此映射将失败。
  • 我还在某些库上发现了一些情况甚至在调用某些方法时抛出UnsupportedOperationException,我不知道为什么。

然后我们重构了所有代码以删除Arrays.asList而不再使用它。

因此,对于一次使用,仅用于打印的示例,它仍然可以接受,但最好不要使用它来传递值/长时间使用。

以上是关于使用Arrays.asList的优点和缺点的主要内容,如果未能解决你的问题,请参考以下文章

Arrays.asList中所遇到的坑

Arrays.asList()用法梳理

使用 Arrays.asList() 初始化列表的最佳方法是啥[重复]

正确认识Arrays.asList方法

为什么Java里的Arrays.asList不能用add和remove方法?

Arrays.asList(array) 和 new ArrayList<Integer>(Arrays.asList(array)) 的区别