Arrays.asList 转换为List 源码分析

93 阅读1分钟

1.代码示例:

`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

2.源码分析:

下面是 java.util.Arrays$ArrayList 的简易源码,我们可以看到这个类重写的方法有哪些。

private static class ArrayList extends AbstractList 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的 add/remove/clear 方法就知道为什么会抛出 UnsupportedOperationException 了。

ArrayList 方法如下:

public E remove(int index) { throw new UnsupportedOperationException(); }

public boolean add(E e) { add(size(), e); return true; }

public void add(int index, E element) { throw new UnsupportedOperationException(); }

public void clear() { removeRange(0, size()); }

protected void removeRange(int fromIndex, int toIndex) { ListIterator it = listIterator(fromIndex); for (int i=0, n=toIndex-fromIndex; i<n; i++) { it.next(); it.remove(); } }

3.解决方法:

**那我们如何正确的将数组转换为 ArrayList呢?

1.最简便的方法 List list = new ArrayList<>(Arrays.asList("a", "b", "c"))

2.使用 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());

3.对于可变集合,你可以使用

List l1 = Lists.newArrayList(anotherListOrCollection); // from collection

List l2 = Lists.newArrayList(aStringArray); // from array

List l3 = Lists.newArrayList("or", "string", "elements"); // from varargs