使用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() 初始化列表的最佳方法是啥[重复]
为什么Java里的Arrays.asList不能用add和remove方法?
Arrays.asList(array) 和 new ArrayList<Integer>(Arrays.asList(array)) 的区别