转载

通过ArrayList.asList方法将数组转成集合后,能否修改集合个数?

通过ArrayList.asList方法将数组转成集合后,能否修改集合个数?

温馨提示:阅读本文需要3-4分钟(少量代码)

今天,我们来解决一个问题:

通过ArrayList.asList方法将数组转成集合后,能否修改集合个数?

人生一切难题,知识给你答案。

数组与集合都是用来存储对象的容器,两者之间可以进行相互转换,数组转集合可以通过Arrays.asList方法。

==ArrayList.asList==

通过ArrayList.asList方法将数组转成集合后,能否修改集合个数?针对这个问题,我们直接给出例子:

public class Demo {
    public static void main(String[] args){
        String[] strings={"A","B","C"};
        List<String> stringList=Arrays.asList(strings);

        stringList.set(0,"G");
        System.out.println(strings[0]);

        stringList.add("M");
    }
}
复制代码

运行结果:

G
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	...
复制代码

通过上面的例子可以发现通过set()方法修改元素的值,原有数组相应位置的值也被修改了,说明修改值没有问题,接着通过调用add()方法直接抛出UnsupportedOperationException异常,说明不能进行修改元素个数的任何操作。

那为什么不能修改元素个数呢?进入Arrays.asList源码中查看:

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
复制代码

发现直接创建了一个ArrayList对象,按照我们平时对ArrayList的理解,应该可以修改元素个数啊?原来这个ArrayList不是我们平时使用的那个ArrayList,它是Arrays的静态内部类ArrayList。

public class Arrays {
    ...
    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) {
            ...
        }

        @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) {
            ...
        }

        @Override
        public boolean contains(Object o) {
            ...
        }

        @Override
        public Spliterator<E> spliterator() {
            ...
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            ...
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            ...
        }

        @Override
        public void sort(Comparator<? super E> c) {
            ...
        }
    }
    ...
}
复制代码

Arrays的静态内部类ArrayList中,set方法本质还是对数组进行值的修改操作,并且静态内部类ArrayList内部没有实现类似add、remove、clear相关方法,所以调用修改元素个数的相关方法时会抛出UnsupportedOperationException异常。

还有一个问题,我们在上面案例中通过set方法修改了ArrayList集合的第一个元素的值,在我们访问原有数组的第一个位置时,值也被改变了,这是为什么呢?

public class Arrays {
    ...
    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的成员变量a使用了final,用于存储集合的数组引用始终被强制指向原有数组。

因此,通过Arrays.asList方法将数组转换成集合后,避免修改元素的个数,否则会引发异常。

通过ArrayList.asList方法将数组转成集合后,能否修改集合个数?
原文  https://juejin.im/post/5c4e58abf265da61616f0ba4
正文到此结束
Loading...