上一篇提及到Arrays的一些常用方法,其中Arrays.asList还是要单独说一下,因为里面的坑太大了,用的时候才发现远远没有想像的那么简单。
坑一、使用集合的修改方法:add()、remove()、clear()会抛出异常
转换的list只可用来做读取操作,想要修改是不行的。值得注意的是,asList方法只适合转换成List之后进行读取的基本操作,虽然转成List集合了,但是底层依然是数组,一不小心就会出现大问题,还是要慎用,坑还是比较大的。Arrays.asList() 方法返回的并不是 java.util.ArrayList ,而是 java.util.Arrays 的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。
阿里巴巴Java手册对其表述如下:
坑二、传递的数组必须是对象数组,而不是基本类型
Arrays.asList()是泛型方法,传入的对象必须是对象数组。比如你创建了一个int数组,想要转成list,调用Array.asList不会报错,但是得到的不是你想要的,举个例子
int[] myArray = { 1, 2, 3 };
List myList = Arrays.asList(myArray);
System.out.println(myList.size());
System.out.println(myList.get(0));
运行结果
1
[I@1540e19d
神不神奇,size大小居然是1,打印的get(0)居然是一个地址(就是数组myArray的地址),为什么会这样,因为当传入一个原生数据类型(int,long,double,float…)数组时,Arrays.asList() 的真正得到的参数就不是数组中的元素,而是数组对象本身!直接把数组当成一个对象进行转化,此时List 的唯一元素就是这个数组,这也就解释了上面的代码。myArray被看作了一个对像。如果把int[] myArray = { 1, 2, 3 };改为Integer[] myArray = { 1, 2, 3 };就没问题了。
Integer[] myArray = { 1, 2, 3 };
List myList = Arrays.asList(myArray);
System.out.println(myList.size());
System.out.println(myList.get(0));
//输出:
3
1
坑三、正确转为ArrayList的方法
-
手动写,学的过程就是敲代码的过程,学习的时候多敲代码没有坏处
-
最简单的方法
List list = new ArrayList<>(Arrays.asList("a", "b", "c"))
-
使用 Java8 的Stream(推荐)
Integer [] myArray = { 1, 2, 3 }; List myList = Arrays.stream(myArray).collect(Collectors.toList()); //基本类型也可以实现转换(依赖boxed的装箱操作) int [] myArray2 = { 1, 2, 3 }; List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList());
其实还有别的方法,自行百度。
List 转 数组直接调用list.toArray()就好了,返回是一个Object[],想改为String的话加参数new String[size];就可以了,随jvm优化,这里的size是0就可以,因为只是为了声明其返回类型。
坑四、不要在for循环里尝试删除ArrayList里的元素
如果要进行remove操作,可以调用迭代器的 remove 方法而不是集合类的 remove 方法。因为如果列表在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身remove/add方法,迭代器都将抛出一个ConcurrentModificationException,这就是单线程状态下产生的 fail-fast 机制。
fail-fast 机制:多个线程对 fail-fast 集合进行修改的时,可能会抛出ConcurrentModificationException,单线程下也会出现这种情况,上面已经提到过。
阿里巴巴开发手册对其解释
回答一下上面的提问。
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
for (String s : list) {
if ("2".equals(s)){
list.remove(s);
}
}
System.out.println(list);
当为1的时候正常运行,换成2的运行结果如下,可以看到ConcurrentModificationException异常出现
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at test.com.A.main(A.java:37)
参考:Java疑难点