概述
该方法是将数组转化成List集合的方法。
List<String> list = Arrays.asList("a","b","c");
注意:
- 该方法适用于对象型数据的数组(String、Integer...)。
- 该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)。
- 该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新。
- 不支持add()、remove()、clear()等方法。
Arrays.asList()是个坑
用此方法得到的List的长度是不可改变的,
当你向这个List添加或删除一个元素时(例如 list.add("d");)程序就会抛出异常(java.lang.UnsupportedOperationException)。怎么会这样?只需要看看asList()方法是怎么实现的就行了:
public static <T> List<T> asList(T... a) {return new ArrayList<>(a);}
当你看到这段代码时可能觉得没啥问题啊,不就是返回了一个ArrayList对象吗?问题就出在这里。
这个ArrayList不是java.util包下的,而是java.util.Arrays.ArrayList
它是Arrays类自己定义的一个静态内部类,这个内部类没有实现add()、remove()方法,而是直接使用它的父类AbstractList的相应方法。
而AbstractList中的add()和remove()是直接抛出java.lang.UnsupportedOperationException异常的!
代码语言:javascript复制public void add(int index, E element) { throw new UnsupportedOperationException();}
public E remove(int index) {throw new UnsupportedOperationException();}
案例
Arrays.asList()
在平时开发中还是比较常见的,我们可以使用它将一个数组转换为一个List集合。
String[] myArray = {"Apple", "Banana", "Orange"};
List<String> myList = Arrays.asList(myArray);
//上面两个语句等价于下面一条语句
List<String> myList = Arrays.asList("Apple","Banana", "Orange");
JDK 源码对于这个方法的说明:
代码语言:javascript复制/**
*返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁,
* 与 Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。
*/
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
使用时的注意事项总结
传递的数组必须是对象数组,而不是基本类型。
Arrays.asList()
是泛型方法,传入的对象必须是对象数组。
public static void main(String[] args) {
int[] myArray = {1, 2, 3};
List myList = Arrays.asList(myArray);
//1
System.out.println(myList.size());
//数组地址值
System.out.println(myList.get(0));
//报错:ArrayIndexOutOfBoundsException
// System.out.println(myList.get(1));
int[] array = (int[]) myList.get(0);
System.out.println(array[0]);//1
}
当传入一个原生数据类型数组时,Arrays.asList()
真正得到的参数就不是数组中的元素,而是数组对象本身!此时List 的唯一元素就是这个数组,这也就解释了上面的代码。
我们使用包装类型数组就可以解决这个问题。
代码语言:javascript复制 public static void main(String[] args) {
int[] myArray = {1, 2, 3};
List myList = Arrays.asList(myArray);
//1
System.out.println(myList.size());
//数组地址值
System.out.println(myList.get(0));
}
使用集合的修改方法:add()
、remove()
、clear()
会抛出异常。
List myList = Arrays.asList(1, 2, 3);
myList.add(4);//运行时报错:UnsupportedOperationException
myList.remove(1);//运行时报错:UnsupportedOperationException
myList.clear();//运行时报错:UnsupportedOperationException
Arrays.asList()
方法返回的并不是 java.util.ArrayList
,而是 java.util.Arrays
的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。
List myList = Arrays.asList(1, 2, 3);
System.out.println(myList.getClass());//class java.util.Arrays$ArrayList
下图是java.util.Arrays$ArrayList
的简易源码,我们可以看到这个类重写的方法有哪些。
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
...
@Override
public E get(int index) {
...
}
@Override
public E set(int index, E element) {
...
}
@Override
public int indexOf(Object o) {
...
}
@Override
public boolean contains(Object o) {
...
}
@Override
public void forEach(Consumer<? super E> action) {
...
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
...
}
@Override
public void sort(Comparator<? super E> c) {
...
}
}
我们再看一下java.util.AbstractList
的remove()
方法,这样我们就明白为啥会抛出UnsupportedOperationException
。
public E remove(int index) {
throw new UnsupportedOperationException();
}
如何正确的将数组转换为ArrayList?
1. 自己动手实现(教育目的)
代码语言:javascript复制//JDK1.5
static <T> List<T> arrayToList(final T[] array) {
final List<T> l = new ArrayList<T>(array.length);
for (final T s : array) {
l.add(s);
}
return l;
}
Integer [] myArray = { 1, 2, 3 };
System.out.println(arrayToList(myArray).getClass());//class java.util.ArrayList
2. 最简便的方法(推荐)
代码语言:javascript复制List list = new ArrayList<>(Arrays.asList("a", "b", "c"))
3. 使用 Java8 的Stream(推荐)
代码语言:javascript复制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());
4. 使用 Guava(推荐)
对于不可变集合,你可以使用ImmutableList
类及其of()
与copyOf()
工厂方法:(参数不能为空)。
List<String> il = ImmutableList.of("string", "elements"); // from varargs
List<String> il = ImmutableList.copyOf(aStringArray); // from array
对于可变集合,你可以使用Lists
类及其newArrayList()
工厂方法:
List<String> l1 = Lists.newArrayList(anotherListOrCollection); // from collection
List<String> l2 = Lists.newArrayList(aStringArray); // from array
List<String> l3 = Lists.newArrayList("or", "string", "elements"); // from varargs
5. 使用 Apache Commons Collections
代码语言:javascript复制List<String> list = new ArrayList<String>();
CollectionUtils.addAll(list, str);
6. 使用 Java9 的 List.of()
方法
Integer[] array = {1, 2, 3};
List<Integer> list = List.of(array);
System.out.println(list); /* [1, 2, 3] */
/* 不支持基本数据类型 */
示例代码
一起来复习一下今天学习到的知识吧。
代码语言:javascript复制public class Test {
public static void main(String[] args){
//1、对象类型(String型)的数组数组使用asList(),正常
String[] strings = {"aa", "bb", "cc"};
List<String> stringList = Arrays.asList(strings);
System.out.print("1、String类型数组使用asList(),正常: ");
for(String str : stringList){
System.out.print(str " ");
}
System.out.println();
//2、对象类型(Integer)的数组使用asList(),正常
Integer[] integers = new Integer[] {1, 2, 3};
List<Integer> integerList = Arrays.asList(integers);
System.out.print("2、对象类型的数组使用asList(),正常: ");
for(int i : integerList){
System.out.print(i " ");
}
// for(Object o : integerList){
// System.out.print(o " ");
// }
System.out.println();
//3、基本数据类型的数组使用asList(),出错
int[] ints = new int[]{1, 2, 3};
List intList = Arrays.asList(ints);
System.out.print("3、基本数据类型的数组使用asList(),出错(输出的是一个引用,把ints当成一个元素了):");
for(Object o : intList){
System.out.print(o.toString());
}
System.out.println();
System.out.print(" " "这样遍历才能正确输出:");
int[] ints1 = (int[]) intList.get(0);
for(int i : ints1){
System.out.print(i " ");
}
System.out.println();
//4、当更新数组或者List,另一个将自动获得更新
System.out.print("4、当更新数组或者List,另一个将自动获得更新: ");
integerList.set(0, 5);
for(Object o : integerList){
System.out.print(o " ");
}
for(Object o : integers){
System.out.print (o " ");
}
System.out.println();
//5、add() remove() 报错
System.out.print("5、add() remove() 报错: ");
// integerList.remove(0);
// integerList.add(3, 4);
// integerList.clear();
}
}