ArrayList集合转换成数组
以String类型为例,我们使用List接口的toArray()方法。
用法1:Object[] toArray();
用法2:<T> T[] toArray(T[] a);
注意这里有两种写法,使用示例如下所示
用法1
List<String> stringList2 = new ArrayList<>();
stringList2.add("A");
stringList2.add("B");
stringList2.add("C");
Object[] objectArray = stringList2.toArray();
用法2
List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.add("B");
stringList.add("C");
String[] stringArray = stringList.toArray(new String[stringList.size()]);
再分析这两种写法的差异之前,我们先做一些知识铺垫
1、system.arraycopy方法的使用
它是一个native方法,他的作用是实现数组之间的复制操作。
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度。
2、ArrayList类中一些全局变量
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
* 我们都知道ArrayList的本质是动态数组,所以底层的elementData是一个Object数组
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
* List的大小
* @serial
*/
private int size;
下面开始讲解这两种toArray的底层原理
用法1:
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
//传入List的内容和大小
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
//整体说一下这块儿的设计思路,如果传来的新数组是一个Object类型,则new一个Object类型的数组,
//否则创建给定类型的数组。注意他们的长度都是List的长度。
//最终执行native方法对数组进行拷贝
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
用法2:
public <T> T[] toArray(T[] a) {
//如果需要转换的数组长度小于List的长度
if (a.length < size)
// 创建并返回一个新的数组
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//否则直接将List的内容拷贝到a数组中
System.arraycopy(elementData, 0, a, 0, size);
//如果要复制的新数组长度大于list的长度,那么将超过list长度后面的值设置为null
if (a.length > size)
a[size] = null;
//返回新数组
return a;
}
//同上所述
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
注意一下坑
当你选择用法一的时候,注意强转的操作
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at com.jd.icity.metadata.controller.Main.main(Main.java:18)
原因是Object[] 数组不能强转成String[]数组;除非这个数组初始化的时候就指向了String[]数组。
可以这样操作
List<String> stringList2 = new ArrayList<>();
stringList2.add("A");
stringList2.add("B");
stringList2.add("C");
Object[] objectArray = stringList2.toArray();
String[] object2StringArray = new String[objectArray.length];
for(int i=0;i<objectArray.length;i++){
object2StringArray[i] =objectArray[i].toString();
}