数组和List是Java开发中常见的两种数据结构,那么如何实现二者之间的快速转换就成了面试官常问的考点之一,下面我们我们就来从数组转List和List转数组两个方面来展开介绍一下。
数组转List
方法一、通过Arrays.asList()
这个方法生成的List是一个固定大小的List,也就是说它的长度不能被修改,即不能添加元素也不能修改元素,因为修改返回的List可能会直接影响到原数组的数据,这里涉及到的知识点叫做引用共享。所谓的引用共享是指当多个变量引用同一个对象的时候,实际上它们共享的是同一个内存地址,因此通过任意一个变量修改对象的内容那么其他的变量也会同步感知到这些修改。因为在Java中除了基本数据类型除外的其他对象都是通过引用来操作的,而非直接操作对象本身,而这种机制就导致了引用共享的现象,有兴趣的读者可以深入进行研究,这里不做过多的介绍。
具体实现如下所示。
String[] array = {"A", "B", "C"};
List list = Arrays.asList(array);
当然如果要返回一个可变的List,我们可以通过如下的方式来实现。
List modifiableList = new ArrayList<>(Arrays.asList(array));
方法二、使用 Collections.addAll()
这种方式创建的List对象是一个可变的对象,可以自由对List进行增删改查,这种实现方式比较灵活,适合需要对结果列表进行进一步操作的场景,如下所示。
String[] array = {"A", "B", "C"};
List list = new ArrayList<>();
Collections.addAll(list, array);
方法三、使用流 (Stream)
在Java8开始提供了Stream的API,所以我们可以通过流式编程的方式来将数组元素转换成List,然后对其进行进一步的操作,如下所示。
String[] array = {"A", "B", "C"};
List list = Arrays.stream(array).collect(Collectors.toList());
当然还有以其他的方式可以实现数组到List的转换,有兴趣的读者可以深入的了解一下,介绍上面的几种实现方式,有一个核心的考点就是引用共享,可能在面试过程中当你提到这个概念的时候,面试官会继续追问什么是引用共享,这里由于篇幅有限,我们先不深入展开介绍,在后续的分享中,我们来详细介绍一下什么引用共享。
介绍完数组转List下面我们就来介绍一下List转数组。
List 转数组
相比数组转List,List转数组会相对来说简单一些,如下所示。
方法一、使用 toArray()
我们可以通过List提供的toArray(T[] a)方法来进行转换,可以看到需要传入一个数组参数对象,如下所示。
List list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
String[] array = list.toArray(new String[0]); // 推荐用法
我们传入的是一个大小为0的参数,那么当参数长度为0的时候,toArray 会动态分配合适大小的新数组,那么如果这个数组涉及的长度较大的时候,我们就可以直接使用传入的数组,这里涉及到的知识点也是引用共享。
方法二、使用流 (Stream)
在Java8以后,我们还可以通过Stream流的方式来实现List转数组,如下所示。
List list = Arrays.asList("A", "B", "C");
String[] array = list.stream().toArray(String[]::new);
通过这种方式,我们可以在完成了过滤、映射等操作之后,在进行数组的转换。
细节和面试回答建议
在面试过程中,除了上面介绍上的方式之外,可能还需要注意如下的一些细节。
第一、性能
选择何种转换方式,主要取决于需求,但也要考虑性能,例如Arrays.asList() 的性能很高,但生成的 List 是不可变长度的,适合小范围的快速转换。Collections.addAll() 和 Stream 方法更灵活,但需要额外的空间分配。
第二、线程安全性
在进行数据结构转换的过程中,如果涉及到多线程的操作,那么就需要考虑到线程安全的问题,例如,可以使用 Collections.synchronizedList() 来包装可变 List,使其达到线程安全的目的。
第三、边界值处理
可能有些面试官会问到,如果数组为空的情况下转换之后的结果是什么?又或者会问到如何处理Null,也就是说如何避免转换结束使用的时候出现 NullPointerException。
第四、需求论
上面提到解决什么样的问题,选择什么样的方式,避免因为错误选择导致系统性能问题。
总结
在上面的介绍中,有一个问题没有回答就是引用共享的问题,在下一篇博客中我们详细来介绍一下什么是引用共享,希望大家多多的关注,敬请期待。