Java 8以上的版本, 提供的 Stream 流式处理大大减少了集合类各种操作(投影、过滤、转换)的代码量,用起来非常香,所以在实际业务开发中,我们常常会把原始的数组转换为 List 类数据结构,使得其可以用上 Stream 流操作。
Arrays.asList方法应该是各位最常用的数组一键转换为 List 的方法了,但是,这个方法有几个特别需要注意的地方,如果不了解的话,排查问题可能会比较困难。
第一个注意点:不能直接使用Arrays.asList来转换基本类型数组
在如下代码中,我们初始化三个数字的int[]数组,然后使用Arrays.asList把数组转换为 List:
但是,这样初始化的 List 并不是我们期望的包含 3 个数字的List,输出结果如下:
可以发现,这个List包含的其实是一个int数组,整个List 的元素个数是 1,元素类型是整数数组。
其原因是,只能是把单个int类型装箱为Integer,不能把int数组装箱为Integer数组。Arrays.asList方法传入的是一个泛型 T 类型可变参数,所以int数组实际上是被整体看成一个对象作为泛型类型 T:
以上,就是第一个坑:不能直接使用Arrays.asList来转换基本类型数组。直接遍历这样的List必然会出现 Bug,修复方式有两种:
1. 最简单的,直接把数组声明为包装类型,不要用int这种基本类型
2. 如果使用 Java8 以上版本可以使用 Arrays.stream 方法来转换,stream 流提供了 boxed 装箱操作:
第二个注意点:Arrays.asList返回的List不支持增删操作
把三个字符串 1、2、3 构成的字符串数组,使用Arrays.asList转换为 List 后,然后为 List 增加一个字符串 4:
结果如下,为 List新增字符串4的操作失败了,报错UnsupportedOperationException:
因为Arrays.asList返回的List并不是我们期望的 java.util.ArrayList,而是Arrays的内部类ArrayList:
ArrayList内部类继承自AbstractList类,并没有覆写父类的 add 方法,而父类中add方法的实现,就是抛出UnsupportedOperationException:
第三个注意点:原始数组的修改会影响Arras.asList返回的那个 List
把三个字符串 1、2、3 构成的字符串数组,使用 Arrays.asList 转换为List后,然后修改原字符串数组的第一个元素为 0:
输出如下,把原始数组的第一个元素从 1 修改为 0 后,asList 获得的 List 中的第一个元素也被修改为 0 了:
看一下ArrayList的实现,可以发现ArrayList其实是直接使用了原始的数组。所以,我们要特别小心,把通过Arrays.asList获得的 List 交给其他方法处理,很容易因为共享数组,相互修改而产生 Bug。