我们都很清楚list带有两个重载的toArray()方法:
- toArray()
- toArray(T[] a)
第一个我就不多解释了,返回的是一个Object数组,实际上用的很少,这篇文章主要想写的是在刷leetcode的题目406. 根据身高重建队列的过程中遇到的List的toArray(T[] a)方法在二维数组复制里的写法。话不多说,先上源码:
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element); the runtime type of the returned
* array is that of the specified array. If the list fits in the
* specified array, it is returned therein. Otherwise, a new array is
* allocated with the runtime type of the specified array and the size of
* this list.
*
* <p>If the list fits in the specified array with room to spare
* (i.e., the array has more elements than the list), the element in
* the array immediately following the end of the collection is set to
* <tt>null</tt>. (This is useful in determining the length of the
* list <i>only</i> if the caller knows that the list does not contain
* any null elements.)
*
* @param a the array into which the elements of the list are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose.
* @return an array containing the elements of the list
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this list
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
-
判断数组a的长度和size的大小,这里
size
是list用来存储元素的数组元素个数,这个变量已经在类里定义好,如果a数组的长度小于size,调用工具类Arrays.copyOf()
方法按照size的大小拷贝数组,elementData就是list用来存储元素的数组,泛型由a.getClass()
得到并且传入。 -
如果数组a的长度length不小于list元素个数,即a.length>=size
将会调用System.arraycopy(elementData, 0, a, 0, size)
将ArrayList里的元素数组elementData中的size个元素拷贝到a数组中。 -
判断a.length >size,如果大于的话,会在a[size]位置设置一个null,置空是为了判断数组结束的位置。
好了,源码就这么多,回归正题,在leetcode二维数组的题目里,一般我们会这么放置元素ArrayList<int[]> list = new ArrayList<>();
,程序结束以后,一般说来会要返回一个int[][]的二维数组,这个时候就要使用到toArray(T[] a)方法,这个时候你会说了,这多简单,这么写:
list.toArray(new int[list.size()][2]);
这里的2是题目设定的2维点坐标。好吧,这样当然是对的,但是我多次运行后,时间和内存效率大概是这样:
其实也可以这么写:
list.toArray(new int[0][]);
解释一下为什么能这样写:
- 二维数组的第2个维度为什么可以不填?因为源码里给出了,我们只需要
a.getClass()
得到泛型,也就是得到int[],并不需要这个数组的长度 - 二维数组的第1个维度为什么可以填0?上面源码分析的第1点已经提到了,传入数组的长度小于list的元素个数size时,是默认使用size作为数组复制的长度
总结
list.toArray(new int[0][])
这种写法确实有性能上的提升,多次运行的时间基本是在9-10秒内,内存占用也在43-44浮动,问了一下大佬,大佬说老手子们在开发中惯用的也是这种写法,所以大家不妨学习一下