Array 转 ArrayList
当需要把 Array
转成 ArrayList
的时候,经常这样做
String[] arr = new String[]{"aa","bb"};
List<String> list = Arrays.asList(arr);
Arrays.asList()
会返回一个 ArrayList
,但是要特别注意,这个 ArrayList
是 Arrays
类的静态内部类,并不是 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
使用过程中的坑就说到这里,欢迎留言补充。
如果觉得还有帮助的话,你的关注和转发是对我最大的支持,O(∩_∩)O: