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:

相关文章
Arrays.asList、ArrayList.subList使用规范
Arrays.asList、ArrayList.subList使用规范
|
3月前
|
Java
CTO的严厉警告:慎用Arrays.asList与ArrayList.subList
【8月更文挑战第13天】在软件开发的世界里,每一个决定都可能对项目的成败产生深远影响。作为CTO,我时常需要站在技术战略的高度,审视团队中的每一个技术选择。今天,我想就两个常被误用或滥用的Java集合操作——Arrays.asList和ArrayList.subList——分享一些深刻的见解,希望能为工作学习中的技术同仁敲响警钟。
28 6
Arrays.asList之后不要调用修改操作
Arrays.asList之后不要调用修改操作
|
Java API Apache
Arrays.asList():使用指南
Arrays.asList() 是一个 Java 的静态方法,它可以把一个数组或者多个参数转换成一个 List 集合。这个方法可以作为数组和集合之间的桥梁,方便我们使用集合的一些方法和特性。本文将给大家介绍 Arrays.asList() 的语法、应用场景、坑点和总结。
199 0
|
Java C++
List.of() Vs Arrays.asList()
在上面的示例中,List.of() 用于创建不可变的颜色列表。任何通过添加或删除元素来修改列表的尝试都将导致抛出异常。 Arrays.asList() 当我们想要由指定数组支持的固定大小(可序列化)集合时,请使用此方法。对返回集合的任何更改也将写入原始数组。 java
69 0
|
Java
Arrays.asList()方法 讲解
Arrays.asList()方法 讲解
116 0
|
Java
Java开发规范01 - 集合篇_Arrays.asList 坑
Java开发规范01 - 集合篇_Arrays.asList 坑
131 0
|
Java C++ 索引
Arrays.asList() vs Collections.singletonList()
看了 IDEA 的告警: 与 Collections.singletonList 比,使用 Arrays.asList 来生成一个list是否更有优势?后者还能使得返回的list不可变。
146 0
|
安全 Java API
Arrays.asList 解析
快速学习方法的定义 | 学习笔记
100 0