数组和List都是我们平时工作,或者主动学习中经常使用的数据结构,在项目中难免会出现需要将其相互转换的场景,同时也正因为此,面试也偶尔会被问到。本文将从其调用的方法,以及其原理、特点展开,希望能让各位读者有所收获,码海无涯,愿与大家共勉。
1,数组转换为List
1,使用Arrays.asList()方法
例如,我们需要将一个含有{
"A", "B", "C"}的数组转为List集合。可以直接调用java提供的一个简单方法Arrays.asList()。
public class ArrayToListExample {
public static void main(String[] args) {
String[] array = {"A", "B", "C"};
List<String> list = Arrays.asList(array);
System.out.println(list);
}
}
但是!值得注意的是,这个列表是固定的,无法进行添加、删除等操作,但是可以进行修改操作。我们都知道List是可以进行扩容的,关于这方面上期文章已经做了详实的解析,有兴趣的读者可以再去看看上一期文章,友情链接:ArrayList源码逐句解析 。那为什么我们已经将其转成了List,还是无法扩容呢?
关键点就在于asList方法,我们可以看看它的源码。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
我们可以很清楚的看到,asList方法调用了Arraylist<>(a),各位读者注意,这个Arraylist<>实际上是我们调用的Arrays当中的一个内部类,不是我们熟知的Arraylist集合,而Arraylist<>(a)是这个内部类中的一个构造方法,同样我们来看看它的源码。
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
//对象引用,并未创建新的对象
}
到这里我们就清楚了,
它只是执行了一个a = Objects.requireNonNull(array),这个语句只是将
a与数组指向同一个地址,并没有新建一个对象,底层还是一个数组。
那么有没有解决办法呢?当然有。我们可以使用ArrayList
构造函数。
2,使用ArrayList
构造函数
同样,我们需要将一个含有{
"A", "B", "C"}的数组转为List集合。
public class ArrayToListExample {
public static void main(String[] args) {
String[] array = {"A", "B", "C"};
List<String> list = new ArrayList<>(Arrays.asList(array));
list.add("D"); // 可以添加元素
System.out.println(list);
}
与直接使用asList方法相比,我们可以再调用一次Arraylist的构造函数,这样就创建出了一个新Arraylist对象,(关于Arraylist的构造函数的原理,友情链接:ArrayList源码分析)而不是简单的引用,并且我们可以看到,我们再往其中添加元素"D"也是可行的。
数组转换为List就分析完毕了,接下来我们来看看,List如何转换为数组?
2,List转换为数组
1,使用toArray方法
与数组转换为List相似,Java的List
接口提供了一个toArray()
方法,可以将list转换为数组。同样我们以包含{
"A", "B", "C"}的集合为例。
public class ListToArrayExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
String[] array = list.toArray(new String[0]); // 推荐使用这种方式,避免自动装箱
System.out.println(Arrays.toString(array));
}
}
其中Arrays.tostring方法是遍历数组并输出的一个方法,读者不必在意,重list.toArray()方法,这是实现
list转换为数组的核心方法,我们看看其源码。
public <T> T[] toArray(T[] a) {
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
我们看其核心代码,System.arraycopy(elementData, 0, a, 0, size),这句代码的意思就是将elementData的数据拷贝到了a中,了解过ArrayLIst底层的读者很清楚elementData就是存储ArrayList元素的数组缓冲区,所以这句代码就是,重新拷贝了一份数据到新的数组中,并返回,所以这里是返回了一个新的对象。
如果你知道数组的类型和大小,也可以预先分配一个数组,然后传递给toArray()
方法。
2,使用toArray(T[] a)
其逻辑与上述逻辑非常类似,读者可以简单看看源码。
public class ListToArrayExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
String[] array = new String[list.size()];
array = list.toArray(array);
System.out.println(Arrays.toString(array));
}
}
可以看到我们预先分配一个Array数组,并以List的大小作为其长度。调用toArray方法,将集合的数据拷贝到该数组。
3,面试题
接下来我们看看一些面试题,读者如果将上面的方法的代码都仔细跟踪阅读过,对于以下面试题就非常轻车熟路了。
面试题1:如何实现数组和List之间的转换?
参考答案: 数组转List,使用JDK中Arrays工具类中的asList方法。 List转数组,使用List中的toArray方法,调用无参方法返回Object数组,传入初始长度的数组对象,返回该数组对象。
面试题2:使用了asList转List后,如果修改了原来数组的内容,List受影响吗?
参考答案:使用asList转List后,如果修改了数组的内容,List会受到影响,因为底层使用的Arrays中的一个内部类arrayList来构造的集合,在调用这个构造方法时,只是将我们传入的这个集合做了包装而已,底层依然指向同一个内存地址。
面试题3:使用了toArray转数组后,如果修改了List内容,数组受影响吗?
参考答案:List调用了toArray转为数组后,如果修改了List内容,数组不会被影响,调用了toArray后,底层进行了数据的拷贝,返回了新的对象,和原来的数据无关,即使修改了原来的数据,数组也不受影响。
标签:toArray,面试题,详细,list,List,数组,array,asList From: https://blog.csdn.net/weixin_52469927/article/details/142936336