美文网首页
java Arrays.asList()

java Arrays.asList()

作者: 王兴岭 | 来源:发表于2020-08-14 15:20 被阅读0次

    在Java中比如想把一个数组转成集合,通常习惯使用Arrays.asList,但是要小心,数组通过Arrays.asList转成集合后,是不能调用集合的add,remove方法的.不然会抛异常UnsupportedOperationException,

    Demo

        Integer[] array = {1, 2};
        List<Object> list = Arrays.asList(array);
        list.remove(1);
    

    控制台结果

    Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.AbstractList.remove(AbstractList.java:161)
        at com.study.webfluxstudy.ArrayListTest.main(ArrayListTest.java:19)
    

    如果新人第一次碰到这个问题可能会感觉很奇怪,add,remove方法不应该是集合的标配吗,怎么会不支持呢?分析下底层源码就知道了

    /**
         * Returns a fixed-size list backed by the specified array.
        */
        @SafeVarargs
        @SuppressWarnings("varargs")
        public static <T> List<T> asList(T... a) {
            return new ArrayList<>(a);
        }
    

    Returns a fixed-size list backed by the specified array.很关键的一句话,asList返回的list是固定大小的,那也就是说生成后的集合就不能再添加删除了,也就是不能add,remove了.注释虽然是这么说,但是如果看方法体中的代码,return new ArrayList<>(a),是不是更奇怪了.ArrayList大家在项目中常用的集合类,add,remove没问题啊.是什么原因呢?
    阅读源码其实就能发现此ArrayList不是彼ArrayList.
    asList静态方法中的ArrayList是Lists中的一个私有静态类,而不是java.util.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);
            }
    
            @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);
            }
        }
    
        public static int hashCode(long a[]) {
            if (a == null)
                return 0;
    
            int result = 1;
            for (long element : a) {
                int elementHash = (int)(element ^ (element >>> 32));
                result = 31 * result + elementHash;
            }
    
            return result;
        }
    

    通过上面的源码可以看到起没有提供add,remove方法的实现,那调用add,remove其实是调用父类的方法

    AbstractList

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

    所以也就能解释为什么Demo演示代码调用add方法,在控制台会抛出UnsupportedOperationException异常了

    如果让Arrays.asList()返回的集合支持add,remove方法

    如果想实现这个目的需要借助java.util.ArrayList帮忙

    public ArrayList(Collection<? extends E> c) {
            elementData = c.toArray();
            if ((size = elementData.length) != 0) {
                // c.toArray might (incorrectly) not return Object[] (see 6260652)
                if (elementData.getClass() != Object[].class)
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
            } else {
                // replace with empty array.
                this.elementData = EMPTY_ELEMENTDATA;
            }
        }
    

    调整后的Demo

        Integer[] array = {1, 2};
        // 通过Arrays转换成的List,保留了原本的类型
        List<Integer> list = Arrays.asList(array);
        System.out.println(list);
        ArrayList<Integer> objects = new ArrayList<Integer>(list);
        objects.add(3);
        System.out.println(objects);
    

    控制台输出

    [1, 2]
    [1, 2, 3]
    

    相关文章

      网友评论

          本文标题:java Arrays.asList()

          本文链接:https://www.haomeiwen.com/subject/poygdktx.html