Arrays.asList注意事项

简介: Arrays.asList注意事项

Array 转 ArrayList

当需要把 Array 转成 ArrayList 的时候,经常这样做



String[] arr = new String[]{"aa","bb"};List<String> list = Arrays.asList(arr);

Arrays.asList() 会返回一个 ArrayList,但是要特别注意,这个 ArrayListArrays 类的静态内部类,并不是 java.util.ArrayList 类。

asList 返回一个由指定数组生成的固定大小的 List

List 是可以动态扩容的,因此在创建一个 List 之后最常见的操作就是向其中添加新的元素或是从里面删除已有元素


public static void main(String[] args) {    String[] arr = new String[]{"aa","bb"};    List<String> list = Arrays.asList(arr);    list.add("Guava");}

尝试运行这段代码,结果抛出了一个 java.lang.UnsupportedOperationException 异常。这一异常意味着,向 list 添加新元素是不被允许的,如果试图从 list 中删除元素,也会抛出相同的异常。

原因是 java.util.Arrays.ArrayList 类实现了 set()get()contains()方法,但是并没有实现增加元素的方法,通过查看源码可以发现调用 add 方法,没有具体实现,仅仅抛出 UnsupportedOperationException 异常,因此它的大小也是固定不变的。

创建一个真正的 ArrayList

为了创建一个真正的 java.util.ArrayList,你应该这样做



String[] arr = new String[]{"aa","bb"};List<String> list = new ArrayList<String>(Arrays.asList(arr));

ArrayList 的构造方法可以接收一个 Collection 类型,而 java.util.Arrays.ArrayList 已经实现了该接口。

不能直接使用 Arrays.asList 来转换基本类型数组

初始化三个数字的 int[] 数组,然后使用 Arrays.asList 把数组转换为 List,代码如下



int[] arr = {1, 2, 3};List list = Arrays.asList(arr);log.info("list:{} size:{} class:{}", list, list.size(), list.get(0).getClass());

这样初始化的 List 并不是我们期望的包含 3 个数字的 List。通过日志可以发现,这个 List 包含的其实是一个 int 数组,整个 List 的元素个数是 1,元素类型是整数数组。


list:[[I@1c53fd30] size:1 class:class [I

来看一下 asList 方法的签名


public static <T> List<T> asList(T... a)

asList 方法的参数必须是对象或者对象数组,而原生数据类型不是对象,当传入一个原生数据类型数组时,asList 的真正得到的参数就不是数组中的元素,而是数组对象本身。

数据类型的数组作为参数正确的方式

如果使用 Java8 以上版本可以使用 Arrays.stream 方法来转换,否则可以把 int 数组声明为包装类型 Integer 数组


int[] arr1 = {1, 2, 3};List list1 = Arrays.stream(arr1).boxed().collect(Collectors.toList());log.info("list:{} size:{} class:{}", list1, list1.size(), list1.get(0).getClass());
Integer[] arr2 = {1, 2, 3};List list2 = Arrays.asList(arr2);log.info("list:{} size:{} class:{}", list2, list2.size(), list2.get(0).getClass());

对原始数组的修改会影响到我们获得的那个 List


String[] arr = {"1", "2", "3"};List list = Arrays.asList(arr);arr[1] = "4";log.info("arr:{} list:{}", Arrays.toString(arr), list);

arr:[1, 4, 3] list:[1, 4, 3]

从日志中可以看出,把原始数组的第二个元素从 2 修改为 4 后,asList 获得的 List 中的第二个元素也被修改为 4 了。

看一下 Arrays 内部类 ArrayList 的实现,可以发现 ArrayList 其实是直接使用了原始的数组。所以,我们要特别小心,把通过 Arrays.asList 获得的 List 交给其他方法处理,很容易因为共享了数组,相互修改产生 Bug。

修复方式比较简单,重新 new 一个 ArrayList 初始化 Arrays.asList 返回的 List 即可


String[] arr = {"1", "2", "3"};List list = new ArrayList(Arrays.asList(arr));arr[1] = "4";log.info("arr:{} list:{}", Arrays.toString(arr), list);

arr:[1, 4, 3] list:[1, 2, 3]

强制类型转换


String[] arr = {"1", "2", "3"};ArrayList<String> list = (ArrayList<String>)Arrays.asList(arr);

java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList

关于 Arrays 使用过程中的坑就说到这里,欢迎留言补充。

推荐阅读:

Java的POJO类为什么要实现Serializable接口

Java的BigDecimal里方法应该这样用

别再用if-else了,用注解去代替他吧

干掉 try catch !

彻底明白如何设计一个良好的 API

如果觉得还有帮助的话,你的关注和转发是对我最大的支持,O(∩_∩)O:

相关文章
|
5月前
|
人工智能 程序员 测试技术
游戏开发成本认知鸿沟:从民间臆测到3A现实的残酷距离-优雅草卓伊凡
游戏开发成本认知鸿沟:从民间臆测到3A现实的残酷距离-优雅草卓伊凡
217 16
游戏开发成本认知鸿沟:从民间臆测到3A现实的残酷距离-优雅草卓伊凡
带你读《深入浅出Dart》十八、Dart的Isolate(1)
带你读《深入浅出Dart》十八、Dart的Isolate(1)
211 0
|
安全 Java API
🌟探索Java宇宙:深入理解Java技术体系与JVM的奥秘
本文深入探讨了Java技术体系的全貌,从Java语言的概述到其优点,再到Java技术体系的构成,以及JVM的角色。旨在帮助Java开发者全面了解Java生态,提升对Java技术的认知,从而在编程实践中更好地发挥Java的优势。关键词:Java, JVM, 技术体系, 编程语言, 跨平台, 内存管理。
145 2
|
人工智能 前端开发 测试技术
探索前端与 AI 的结合:如何用 GPT-4 助力开发效率
本文介绍了 GPT-4 如何成为前端开发者的“神队友”,让开发变得更加高效愉快。无论是需求到代码的自动生成、快速调试和性能优化,还是自动化测试和技术选型,GPT-4 都能提供极大的帮助。通过智能生成代码、捕捉 BUG、优化性能、自动化测试生成以及技术支持,GPT-4 成为开发者不可或缺的工具,帮助他们从繁重的手动任务中解脱出来,专注于创新和创意。GPT-4 正在彻底改变开发流程,让开发者从“辛苦码农”转变为“效率王者”。
393 0
探索前端与 AI 的结合:如何用 GPT-4 助力开发效率
|
算法 测试技术 程序员
力扣经典150题第二十七题:两数之和 II - 输入有序数组
力扣经典150题第二十七题:两数之和 II - 输入有序数组
101 1
|
Web App开发
【无标题】推荐一个非常好用的GitHub插件
【无标题】推荐一个非常好用的GitHub插件
115 0
|
SQL 关系型数据库 分布式数据库
分布式关系型数据库服务DRDS——拆分键
分布式关系型数据库服务DRDS——拆分键自制脑图, 即分库/分表字段。 DRDS 根据拆分键的值将数据表水平拆分到后端的每一个 RDS 分库里。DRDS 里除了可以定义分库键以外,每一张逻辑表都可以定义自己的拆分键。拆分键暂时只能是单个字段。如果分库键与分表键相同,那么在插入时只需要指定该分库/分表键。如果分库键与分表键不同则在插入时需要同时指定分库键和分表键。
854 0
分布式关系型数据库服务DRDS——拆分键
|
计算机视觉 iOS开发 Python
python之pyinstaller打包问题系列(二)
学会冷静分析,学会根源排查。
1324 0
 python之pyinstaller打包问题系列(二)
|
存储 NoSQL 算法
the-way-to-go - 4. Redis 数据类型 Set 集合
the-way-to-go - 4. Redis 数据类型 Set 集合
184 0
|
JavaScript 前端开发
JS生成随机验证码校验(前端)
JS生成随机验证码校验(前端)