使用Arrays.asList的优点和缺点

时间:2012-11-14 07:52:32

标签: java arrays collections

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

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

5 个答案:

答案 0 :(得分:6)

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

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

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

但如果您不喜欢上述方法,您可能也想这样做:

Collections.addAll(arraylist, array);

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


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

答案 1 :(得分:2)

  

我想知道使用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 比使用它更简单,更便宜

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

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

来自 有效的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:数组中的asList(Object [])无法应用于(int [])     的System.out.println(Arrays.asList(位));

由于不幸的决定在版本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));

答案 4 :(得分:0)

从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并不再使用它。

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