在Java中,数组和ArrayList是用于存储元素列表的最常见的两种数据结构。而且,经常需要在它们之间进行转换。面对这样高频的一个转换需求,我们有必要寻找到一种高效的方法。那么什么样的转换方式才是最高效的呢?本文将带领大家一步一步推导出最后的答案。首先,我们把这个场景实例化为一个具体问题:如何把如下所示的 数组 转换成 ArrayList ?
Element[] array = {new Element(1),new Element(2),new Element(3)};
常见方法
对于熟悉 Arrays 工具类的读者而言,可能会提出如下的这个解决方法:
ArrayList arrayList = new ArrayList(Arrays.asList(array));
针对此方法,我们首先查看一下 Java Doc 中对于 ArrayList 的构造方法是如何描述的:
ArrayList(Collection< ? extends E > c) : Constructs a list containing the elements of the specified collection, in the order they are returned by the colleciton’s iterator.
所以,ArrayList 的构造方法会执行如下的两个操作:
1. 把 collection 转换成一个 数组
2. 把 数组 中的所有元素拷贝到 ArrayList 的底层数组 elementData 中。
我们来直接看一眼 ArrayList 的构造函数的源码:
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
错误方法
另一个简单、直接的方法是:
List list = Arrays.asList(array);
这个方法似乎是最简单。但是,该方法却并不好,Arrays.asList 方法返回的 list 是一个固定大小的 List。实际上,此处返回的这个 list, 它的类型并不是我们常见的 java.util.ArrayList ,而是定义于 java.util.Arrays 内部的一个私有静态内部类。我们知道 ArrayList 本质上是利用一个数组(array)来实现的,而且此处从 asList() 方法返回的这个 list 是固定大小的List,list 的大小由原始的数组大小决定。在此种情况下,如果我们在 list 的基础上新增或者删减元素,程序就会抛出一个 UnsupportedOperationException 异常。
list.add(new Element(4));
Exception in thread "main" java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
at collection.ConvertArray.main(ConvertArray.java:22)
终极方法
针对上述两个方法的一些明显缺点,有人提出了一个改进方法:
Element[] array = {new Element(1), new Element(2)};
List list = new ArrayList(array.length);
Collections.addAll(list, array);
这个方法利用 Collections 工具类的 addAll 方法,消除了“常见方法”中 数组转Collection,Collection再转数组 的这两个冗余过程,同时,消除了“错误方法”中获得的最终list是一个固定大小List的错误。
结论
实际上,这不是一个很难的问题,但确实一个非常有意思的问题。可能,每一个Java程序员都了解ArrayList,但是解决此问题的过程中,很可能会犯一些小错误。至于这三个方法的性能对比试验,有兴趣的读者请自己尝试。
转:http://www.tiantianbianma.com/java-array-convert-arraylist.html/