Java Arrays 和 List的相互转化
最近在 leetcode 刷题的时候遇到过好几次这样的情况:需要返回的数据类型是数组(Arrays
),但是求解的时候并不知道数组的长度,这时候就需要先用 List
进行临时存储,最后再转化为 Arrays
返回。所以这里将 java 中 Arrays
和 List
之间的转化总结一下。
Arrays
转为 List
1. 利用Arrays.asList()
方法
Arrays
类提供了 asList()
方法,我们先来看看源码:
可以看到,Arrays.asList()
是泛型方法,传入的必须是对象数组而不是基本数据类型的数组。首先拿 String
数组来看一下:
没有问题,数组“变成了” List
,并且可以通过List
的 get()
方法进行元素访问。但是换成 int[]
数组呢?
Eclipse提示出错了,需要将 List
的元素类型换成 int[]
,也就是说对于基本数据类型的数组,Arrays.asList()
会将整个数组作为一个最后返回的列表中的一个对象。不信的话就改成 int[]
试一下,看结果:
所以,对于基本数据类型的数组,是不能用 Arrays.asList()
将其转化为 List
的。
另一个坑
是不是以为对于对象数组,Arrays.asList()
就可以无脑使用了呢?还是图样图森破啊。再看看源码:
发现了吧!Arrays.asList()
这里返回的ArrayList
并不是java.util.ArrayList
,而是java.util.Arrays
自己定义的一个静态内部类,这个内部类继承了AbstarctList
类。并且,这个自定义的内部类并没有实现java.util.List
的修改方法例如add
、remove
等。因此对于转化后的List对象如果进行修改会报异常!!
2. 使用 Java8 的Stream
接口
挖完坑之后当然是要填坑了。其实自己实现Arrays
转为 List
最简单的就是遍历添加了,不用多说。这里说一个Java8以上版本中的高级操作——Stream接口,这个接口主要就是用来支持对元素流的函数式操作,更详细的介绍可以参考官方文档。先给出转化代码:
public static void main(String[] args) {
int[] arr = {1, 2, 3};
List<Integer> ls = Arrays.stream(arr).boxed().collect(Collectors.toList());
System.out.println(ls.get(0));
}
上面代码得到的 ls
支持列表的元素操作函数。Arrays.stream()
函数返回一个IntStream
对象(存储原始int
类型的Stream
),boxed()
函数是 IntStream
对象的装箱函数,返回Stream<Integer>
对象。collect()
函数根据指定的Collector
对流元素进行对应操作,上面代码中 Collectors.toList()
返回一个将所有元素收集到一个 List
中的 Collector
。
List
转为 Arrays
1. 使用 List.toArray()
方法
List
有两个toArray()
方法,其中无参的toArray()
方法返回的是Object[]
数组,也无法通过强制类型转换转换成别的类型(所以不明白无参的这个方法应用场景在哪里)。此外还有一个有参的泛型方法 <T> T[] toArray(T[] a)
,这个方法可以返回指定类型的数组,但是也只能是引用类型:
List<String> ls = new ArrayList<>();
ls.add("java");
ls.add("python");
ls.add("php");
String[] arr = ls.toArray(new String[0]);
System.out.println(arr[1]);
像这样就没问题,但是对于基本数据类型像char
、int
这样就会报错,必须指定为对应的包装类才可以。因此即使是 <T> T[] toArray(T[] a)
这个方法,也无法直接将Integer
的列表转化为int[]
数组。
2. 使用 Java8 的Stream
接口
以List<Integer>
到 int[]
为例,下面这段代码就可以实现转化:
List<Integer> ls = new ArrayList<>();
ls.add(1);
ls.add(3);
ls.add(4);
int[] arr = ls.stream().mapToInt(Integer::intValue).toArray();
System.out.println(arr[1]);
首先通过stream()
方法将列表转化为流对象,再通过mapToInt()
函数将流对象中的元素映射成int
类型,最后通过Stream
的 toArray
方法转化为数组。其中mapToInt()
参数为给定的映射函数,这里表示映射到int
类型。::
也是java8中的操作符,表示对Integer
类的intValue()
方法的调用,更多的使用方式可以看官方文档。
总结
Java集合中只能存放引用类型的数据,不能存放基本数据类型,因此在对基本数据类型数据进行“Arrays-to-List”或者“List-to-Arrays”操作的时候,类本身的方法可能不适用,这时候就必须手动遍历转化,或者利用Java8的Stream
接口帮助实现。上面的实现看起来好像是把简单问题变复杂了,确实在进行简单转化的时候遍历复制元素是最方便的,但是Stream
接口还有一些强大的功能,如果转化过程中还有一些复杂操作像元素筛选、过滤等 Stream
接口就能够用到了。
最新文章
- LVS
- 关于Mapper、Reducer的个人总结(转)
- 十大技巧优化Android App性能
- Java笔记之数组
- linux内核系列(二)内核数据结构之链表
- struts2面试题
- STL源码剖析 迭代器(iterator)概念与编程技法(三)
- [HMLY]9.深入浅出-iOS Reactive Cocoa的常见用法
- 实战DeviceIoControl 之五:列举已安装的存储设备
- spring boot + mybatis + druid配置实践
- HEOI2013SAO
- js如何实现类的继承
- a链接的onclick与js中的return false
- Spring点滴十一:Spring中BeanFactoryPostProcessor和BeanPostProcessor区别
- [PureScript] Basic Data Constructors in PureScript
- iOS 获取已安装 的APP
- .Net Core 使用依赖注入
- apache如何支持asp.net
- 【WPF】C#代码动态改变控件的样式
- CSS3 简介
热门文章
- vue项目中视频播放结束返回首页出现1秒左右的白屏问题
- 适用于 deno 的多版本管理工具 dvm 发布
- selenium-自动化测试51job网站(MacOS + Safari)2020年10月6日
- centos7卸载mariadb安装mysql
- USB口,串口,以太网口简介
- K-DTree入门
- VS Code对Golang的基准测试研究
- vue-integer-plusminus
- 使用git 版本控制的代码在线修调试,如何还原
- org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, ";enterpCd";)-Mybatis报错