当前位置:首页 > 技术文章 > 正文内容

面试官-如何实现数组和 List 之间的转换?

zonemu21小时前技术文章2

数组和List是Java开发中常见的两种数据结构,那么如何实现二者之间的快速转换就成了面试官常问的考点之一,下面我们我们就来从数组转List和List转数组两个方面来展开介绍一下。

数组转List

方法一、通过Arrays.asList()

这个方法生成的List是一个固定大小的List,也就是说它的长度不能被修改,即不能添加元素也不能修改元素,因为修改返回的List可能会直接影响到原数组的数据,这里涉及到的知识点叫做引用共享。所谓的引用共享是指当多个变量引用同一个对象的时候,实际上它们共享的是同一个内存地址,因此通过任意一个变量修改对象的内容那么其他的变量也会同步感知到这些修改。因为在Java中除了基本数据类型除外的其他对象都是通过引用来操作的,而非直接操作对象本身,而这种机制就导致了引用共享的现象,有兴趣的读者可以深入进行研究,这里不做过多的介绍。

具体实现如下所示。

String[] array = {"A", "B", "C"};
List<String> list = Arrays.asList(array);

当然如果要返回一个可变的List,我们可以通过如下的方式来实现。

List<String> modifiableList = new ArrayList<>(Arrays.asList(array));

方法二、使用 Collections.addAll()

这种方式创建的List对象是一个可变的对象,可以自由对List进行增删改查,这种实现方式比较灵活,适合需要对结果列表进行进一步操作的场景,如下所示。

String[] array = {"A", "B", "C"};
List<String> list = new ArrayList<>();
Collections.addAll(list, array);

方法三、使用流 (Stream)

在Java8开始提供了Stream的API,所以我们可以通过流式编程的方式来将数组元素转换成List,然后对其进行进一步的操作,如下所示。

String[] array = {"A", "B", "C"};
List<String> list = Arrays.stream(array).collect(Collectors.toList());

当然还有以其他的方式可以实现数组到List的转换,有兴趣的读者可以深入的了解一下,介绍上面的几种实现方式,有一个核心的考点就是引用共享,可能在面试过程中当你提到这个概念的时候,面试官会继续追问什么是引用共享,这里由于篇幅有限,我们先不深入展开介绍,在后续的分享中,我们来详细介绍一下什么引用共享。

介绍完数组转List下面我们就来介绍一下List转数组。

List 转数组

相比数组转List,List转数组会相对来说简单一些,如下所示。

方法一、使用 toArray()

我们可以通过List提供的toArray(T[] a)方法来进行转换,可以看到需要传入一个数组参数对象,如下所示。

List<String> 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<String> list = Arrays.asList("A", "B", "C");
String[] array = list.stream().toArray(String[]::new);

通过这种方式,我们可以在完成了过滤、映射等操作之后,在进行数组的转换。

细节和面试回答建议

在面试过程中,除了上面介绍上的方式之外,可能还需要注意如下的一些细节。

第一、性能

选择何种转换方式,主要取决于需求,但也要考虑性能,例如Arrays.asList() 的性能很高,但生成的 List 是不可变长度的,适合小范围的快速转换。Collections.addAll()Stream 方法更灵活,但需要额外的空间分配。

第二、线程安全性

在进行数据结构转换的过程中,如果涉及到多线程的操作,那么就需要考虑到线程安全的问题,例如,可以使用 Collections.synchronizedList() 来包装可变 List,使其达到线程安全的目的。

第三、边界值处理

可能有些面试官会问到,如果数组为空的情况下转换之后的结果是什么?又或者会问到如何处理Null,也就是说如何避免转换结束使用的时候出现 NullPointerException

第四、需求论

上面提到解决什么样的问题,选择什么样的方式,避免因为错误选择导致系统性能问题。

总结

在上面的介绍中,有一个问题没有回答就是引用共享的问题,在下一篇博客中我们详细来介绍一下什么是引用共享,希望大家多多的关注,敬请期待。

相关文章

Linux 发行版介绍 Zenwalk Linux(linux发行版2021)

Zenwalk Linux是基于Slackware的GNU/Linux发行版, 100%兼容Slackware。 致力于精简和快捷的图形桌面及多媒体使用。包含整套编程环境和运行库,还提供了常用服务器套...

据说是可以替代 Windows 的 5个 Linux 发行版

现如今有数以千计的 Linux 发行版可供您使用,然而人们却无法选择一个完美的操作系统来替代 Windows。 使用 Windows 时,傻瓜都能操作自如,同样的方法却不适用于 Linux。在这里,您...

「图解」父子组件通过 props 进行数据交互的方法

1.组件化开发,经常有这样的一个场景,就是父组件通过 Ajax 获取数据,传递给子组件,如何通过 props 进行数据交互来实现,便是本图解的重点。2.代码的结构3.具体代码 ①在父组件 data 中...

vue:组件中之间的传值(vue组件之间传参)

一、父子组件之间的传值----props/$emit1、父组件向子组件传值--props2.子组件想父组件传值-this.$emit('select',item)二、父组件向下(深层)...

【Vue3 基础】05.组件化(组件使用vuex)

这是 Vue3 + Vite + Pinia +TS + Element-Plus 实战系列文档。最近比较忙没什么时间写文章,争取早日把这个系列完结吧~生命周期和模板引用在本章之前,我们通过响应式 a...

Vue3开发极简入门(16):祖孙组件间通信之provide&amp;inject

前文说了Vue的组件间关系,有父子、爷孙、其他关系。例如之前的Father、Son是父子关系,App与Son就是爷孙关系。而props的Son,与emits的Son,就是其他关系。前文的props是父...