1.Arrays.asList(T..)使用的是静态内部类:ArrayList, (没有定义add和remove等一些方法),而不是java.util.ArrayList
/**
* 1.测试Arrays.asList()方法
* @author zhangdi
* @description
* 使用的是静态内部类:ArrayList, (没有定义add和remove等一些方法),而不是java.util.ArrayList
* 接受的参数被一个final修饰的成员变量 private final E[] a接受
* 调用Arrays.asList()的add和remove方法 会抛异常:java.lang.UnsupportedOperationException
*/
@Test
public void testAsListOfArray() {
List<String> list = Arrays.asList("1", "2", "3");
list.add("4");
for (String string : list) {
System.out.println("string:" + string);
}
}
@Test
public void testAsListOfArray2() {
List<String> list = new ArrayList<>();
list.add("5");
list.add("6");
list.add("7");
list.add("8");
for (String string : list) {
System.out.println("string:" + string);
}
}
2.为什么List<int[]> asList2 = Arrays.asList(d);
返回的是List<int[]>
而不是List<int>
呢?为什么testAsListOfArray3
中的list.size():
输出1而不是4呢?
/**
* 2.Array.asList()接收基本类型与单个元素
* @author zhangdi
* @see https://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should
*/
@Test
public void testAsListOfArray3(){
//1
int[] f = {1,2,3,4};
List list = Arrays.asList(f);
System.out.println("list.size():"+list.size()); //output: list.size():1
//2
int[] a = {1,2,3,4,8,10,22,12,214,23};
String[] b = {"a","b","c"};
Integer[] c = {1,2,3,4,8,10,22,12,214,23};
System.out.println(Arrays.asList(a));
System.out.println(Arrays.asList(b));
System.out.println(Arrays.asList(c));
//3
//There's no such thing as a List<int> in Java - generics don't support primitives.
//Autoboxing only happens for a single element, not for arrays of primitives.
//java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
int[] d = new int[]{1,2,3,4,8,10,22,12,214,23};
Integer[] e = new Integer[]{1,2,3,4,8,10,22,12,214,23}; //避免使用原始类型数组作为asList的输入参数
List<int[]> asList2 = Arrays.asList(d);
List<Integer> asList3 = Arrays.asList(e);
System.out.println(asList2);
System.out.println(asList3);
// output:
/*
1
[[I@232d49d1] //会被当做一个参数接收
[a, b, c]
[1, 2, 3, 4, 8, 10, 22, 12, 214, 23]
[[I@ef05133d]
[1, 2, 3, 4, 8, 10, 22, 12, 214, 23]
*/
}
因为:Arrays.asList()方法接受一个可变参数T,一般可看做数组参数,但是因为int[] 本身就是一个类型,所以a变量作为参数传递时,编译器认为只传了一个变量,这个变量的类型是int数组,所以size为1,相当于是List中数组的个数。基本类型是不能作为泛型的参数,要想作为泛型化参数就必须使用其对应的包装类型。 按道理此处应该使用包装类型,但这里却没有报错,因为数组是可以泛型化的,所以转换后在list中就有一个类型为int的数组; 所以 ,以后要避免使用原始类型数组作为asList的输入参数.
另外,java8的一些写法:学习一下
//1
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
//2
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
- 自己实现一个asList方法,能够add和remove; (比较一下自己和源码的写法)
/**
* @author zhangdi
* @param strings
* @return 目的也是为了让返回的list是一个可操作的list
* @description jdk 中Arrays.asList()是一个静态方法:
*/
@SafeVarargs
private static <T> List<T> asList(T... args) {
List<T> list = new ArrayList<>();
for (T a : args) {
list.add(a);
}
return list;
}
Arrays.asList()的手写第二个版本(目的也是为了让返回的list是一个可操作的list):
/**
* @author zhangdi
* @param a
* @return
* @description asList_v2 比用for更为简洁
*/
@SafeVarargs
public static <T> List<T> asList_v2(T... a) {
List<T> list = new ArrayList<T>();
Collections.addAll(list, a);
return list;
}
实际上,addAll底层用的也是for循环,还有一个 result |= c.add(element);操作,可以学习一下
/**
* jdk_source:
* 把所有指定元素添加到集合c中, 有一个元素添加成功就返回true
*/
public static <T> boolean addAll(Collection<? super T> c, T... elements) {
boolean result = false;
for (T element : elements)
result |= c.add(element);
return result;
}
jdk源码 – Arrays.asList(T… a) :
从这个内部类ArrayList的实现可以看出,它继承了类AbstractList,但是没有重写add和remove方法,没有给出具体的实现。查看一下AbstractList类中对add和remove方法的定义,如果一个list不支持add和remove就会抛出UnsupportedOperationException。
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* @serial include
*/
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);
}
@Override
public int size() {
return a.length;
}
@Override
public Object[] toArray() {
return a.clone();
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
@Override
public E get(int index) {
return a[index];
}
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
@Override
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
action.accept(e);
}
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
E[] a = this.a;
for (int i = 0; i < a.length; i++) {
a[i] = operator.apply(a[i]);
}
}
@Override
public void sort(Comparator<? super E> c) {
Arrays.sort(a, c);
}
}
参考:
https://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should
https://blog.csdn.net/bruce128/article/details/21640479