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

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

zonemu2个月前 (07-10)技术文章19

数组和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

第四、需求论

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

总结

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

相关文章

零基础开始学 Web 前端开发,有什么建议?(附视频教程)

WEB前端看似简单,其实不然,要学的知识点很多很杂,对于零基础学习前端的小伙伴来说,一份详细的前端学习知识点大纲尤为重要。下面,话不多说,直接上干货(全网最全,没有之一)。PS:文末有福利(全阶段视频...

Windows 下 Git 拉 Gitlab 代码(gitlab拉项目)

读者提问:『阿常你好,Windows 下 Git 拉 Gitlab 代码的操作步骤可以分享一下吗?』阿常回答:好的,总共分为五个步骤。一、Windows 下安装 Git官网下载链接:https://g...

程序员开发必会之git常用命令,git配置、拉取、提交、分支管理

整理日常开发过程中经常使用的git命令!git配置SSH刚进入项目开发中,我们首先需要配置git的config、配置SSH方式拉取代码,以后就免输入账号密码了!# 按顺序执行 git config -...

GIT最佳实践,高效提升多团队协同开发效率

多个团队共同维护同一个微服务模块时,经常出现A团队已发布的功能,B团队提交测发布出现冲突或缺失,如何有效解决多团队共同维护的问题呢?常用的版本管理工具有GIT、SVN,这两种版本管理工具,各有千秋;虽...

K8s 的 Namespace 到底解决了什么问题?

在 Kubernetes 的世界里,资源调度、服务编排以及自动化运维构成了它强大的基础架构能力。但随着集群规模的扩大和团队协作复杂度的提升,仅靠原始的资源管理手段已经难以支撑多租户或大型项目的管理需求...

Jenkins 学习笔记(jenkins要学多久)

本学习笔记参考《Jenkins 2.x实践指南》。1. Jenkins 简介#Jenkins 是一款自动化的任务执行工具。通常用于持续集成/持续交付领域。可以通过界面或Jenkinsfile告诉Jen...