大家好,欢迎来到IT知识分享网。
我们在日常的开发中,常常使用到Arrays.asList()这个方法,它能够很轻易地将一个数组转化为一个List。
例如:
Integer[] a = new Integer[]{1, 2, 3};
List<Integer> list = Arrays.asList(a);
现在已经是一个List了,我想对这个List做一些基本操作。
list.add(4);
运行这段语句后,居然出现了java.lang.UnsupportedOperationException,什么情况,不支持这个新增操作吗?进到源码里,一探究竟。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
不就是返回了一个ArrayList吗?ArrayList什么时候不支持add方法了,再点进这个“ArrayList”里
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
...
}
哦,原来此“ArrayList”不是我们经常用到的那个ArrayList,这个只是Arrays的一个内部类而已。此外,这个“ArrayList”继承AbstractList,却并没有重写它的set、add、remove方法,AbstractList源码如下所示。
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
还有一个很重要的一点就是,这个“ArrayList”的构造方法,对传进来的数组没有做任何处理,仅仅是直接使用。那么,我们改变原数组中某个索引下标的元素,“ArrayList”也会做同样的改变。
好,既然这个“ArrayList”仅仅支持集合常用的get方法,那现在看这个例子,这一次我使用基本数据类型的数组。
int[] a = new int[]{1, 2, 3};
List list = Arrays.asList(a);
System.out.println(list.get(0));
System.out.println(list.get(1));
直接运行后,就报出了如下的错误
[I@1b6d3586
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 1
at java.util.Arrays$ArrayList.get(Arrays.java:3841)
at com.yang.testList.Main.main(Main.java:12)
看的出来,这个“ArrayList”第一个元素输出是一个地址,尝试获取第二个元素时,直接就越界了。
原来啊,这个Arrays.asList()方法是一个泛型方法,需要的是一个对象类型的数组,而不是一个基本数据类型的数组。现在我们直接传入基本数据类型的数组,这个“ArrayList”的构造方法无法将基本类型的数组传到参数E[] a中,只能将一整个数组当作E[] a的第一个元素,因此get(0)时,获取到了这个基本数据类型数组的地址首值,而get(1)时,直接产生了越界异常。
看来,Arrays.asList坑挺多啊,那么,有什么其他方法能够将数组转为List呢?
(1)将Arrays.asList()构造出来的“ArrayList”传入java.util.ArrayList的构造方法里。
Integer[] a = new Integer[]{1, 2, 3};
List list = Arrays.asList(a);
ArrayList arrayList = new ArrayList<>(list);
这个构造方法使用 Arrays.copyOf方法,因此java.util.ArrayList内部的数组和传入的数组将不会有任何的关系。关于数组复制效率的问题,可以参考我的另外一篇文章【JAVA】数组复制效率的比较
(2)使用stream
Integer[] a = new Integer[]{1, 2, 3};
List<Integer> collect = Arrays.stream(a).collect(Collectors.toList());
基本数据类型,可以先转化为Stream,再进行装箱即可。
int[] b = new int[]{1, 2, 3};
List<Integer> list = Arrays.stream(b).boxed().collect(Collectors.toList());
不过,使用stream进行转换,可能涉及效率问题,这篇文章暂不考虑。
(3)使用Guava
如果说,需要一个不可变集合,可以使用ImmutableList.copyOf方法
Integer[] a = new Integer[]{1, 2, 3};
List<Integer> list = ImmutableList.copyOf(a);
可变集合,可以使用Lists.newArrayList方法
Integer[] a = new Integer[]{1, 2, 3};
List<Integer> list = Lists.newArrayList(a);
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/15261.html