zoukankan      html  css  js  c++  java
  • Java数组转集合与集合转数组的坑

    Java中将数组转为集合,会用到Arrays.asList()的方法,然而,这个方法却与我们的预期期望存在一些出入,当用到asList方法将数组转化成List列表时,对得到的List列表进行add()和remove()操作, JVM会抛出异常:java.lang.UnsupportedOperationException异常 

    Arrays.asList返回的是同样的ArrayList,为什么就不能使用add和remove方法呢?

    接下来我们来看一下Arrays.asList 源码 

      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")

    AbstractList源码:

    public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
        /**
         * Sole constructor.  (For invocation by subclass constructors, typically
         * implicit.)
         */
        protected AbstractList() {
        }
    
        /**
         * Appends the specified element to the end of this list (optional
         * operation).
         *
         * <p>Lists that support this operation may place limitations on what
         * elements may be added to this list.  In particular, some
         * lists will refuse to add null elements, and others will impose
         * restrictions on the type of elements that may be added.  List
         * classes should clearly specify in their documentation any restrictions
         * on what elements may be added.
         *
         * <p>This implementation calls {@code add(size(), e)}.
         *
         * <p>Note that this implementation throws an
         * {@code UnsupportedOperationException} unless
         * {@link #add(int, Object) add(int, E)} is overridden.
         *
         * @param e element to be appended to this list
         * @return {@code true} (as specified by {@link Collection#add})
         * @throws UnsupportedOperationException if the {@code add} operation
         *         is not supported by this list
         * @throws ClassCastException if the class of the specified element
         *         prevents it from being added to this list
         * @throws NullPointerException if the specified element is null and this
         *         list does not permit null elements
         * @throws IllegalArgumentException if some property of this element
         *         prevents it from being added to this list
         */
        public boolean add(E e) {
            add(size(), e);
            return true;
        }
    
        /**
         * {@inheritDoc}
         *
         * @throws IndexOutOfBoundsException {@inheritDoc}
         */
        abstract public E get(int index);
    
        /**
         * {@inheritDoc}
         *
         * <p>This implementation always throws an
         * {@code UnsupportedOperationException}.
         *
         * @throws UnsupportedOperationException {@inheritDoc}
         * @throws ClassCastException            {@inheritDoc}
         * @throws NullPointerException          {@inheritDoc}
         * @throws IllegalArgumentException      {@inheritDoc}
         * @throws IndexOutOfBoundsException     {@inheritDoc}
         */
        public E set(int index, E element) {
            throw new UnsupportedOperationException();
        }
    
        /**
         * {@inheritDoc}
         *
         * <p>This implementation always throws an
         * {@code UnsupportedOperationException}.
         *
         * @throws UnsupportedOperationException {@inheritDoc}
         * @throws ClassCastException            {@inheritDoc}
         * @throws NullPointerException          {@inheritDoc}
         * @throws IllegalArgumentException      {@inheritDoc}
         * @throws IndexOutOfBoundsException     {@inheritDoc}
         */
        public void add(int index, E element) {
            throw new UnsupportedOperationException();
        }
    
        /**
         * {@inheritDoc}
         *
         * <p>This implementation always throws an
         * {@code UnsupportedOperationException}.
         *
         * @throws UnsupportedOperationException {@inheritDoc}
         * @throws IndexOutOfBoundsException     {@inheritDoc}
         */
        public E remove(int index) {
            throw new UnsupportedOperationException();
        }

    由源码可见,UnsupportedOperationException 是AbstractList抛出的,因为Arrays中的ArrayList并没有实现remove()和add()方法,所以抛出了异常。 
    所以说 Arrays.asList 返回的 List 是一个不可变长度的列表,此列表不再具备原 List 的很多特性,因此慎用 Arrays.asList 方法。


    ArrayList中构造方法:

     ArrayList(E[] array) {
                a = Objects.requireNonNull(array);
            }

    看一段这样的代码: 

    import java.util.Arrays;
    import java.util.List;
    
    public class Test2{
        public static void main(String[] args) {
            int[] array = new int[]{1,2,3,4,5};
            List list = Arrays.asList(array);
            System.out.println(list.size());
        }
    }

    Arrays 的内部类 ArrayList 构造方法接收的是一个泛型数组,即数组类型不能为基本类型,应该为其对应的包装类型(传即入引用类型),否则传入的基本类型的整个数组,将被编译器视为一个引用参数,

    所以原始类型不能作为 Arrays.asList 方法的参数,否则会被当做一个参数


    再来看看在Java中将集合转为数组,ArrayList提供了一个将List转为数组的一个非常方便的方法toArray。toArray有两个重载的方法:

      @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;
            }

    对于第一个重载方法,是将list直接转为Object[] 数组;

    第二种方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。

     若采用第一种toArray方法,是这样写:

    1 ArrayList<String> list=new ArrayList<String>();
    2         for (int i = 0; i < 10; i++) {
    3             list.add(""+i);
    4         }
    5          
    6         String[] array= (String[]) list.toArray();

    结果一运行,报错:

    Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

    第一个方法不能将Object[] 转化为String[],我们需要修改为:

    1 Object[] arr = list.toArray();
    2         for (int i = 0; i < arr.length; i++) {
    3             String e = (String) arr[i];
    4             System.out.println(e);
    5         }

    建议用第二种方法:普通数组基本类型必须改为包装类

    import java.util.ArrayList;
    import java.util.List;
    
    public class Test2{
        public static void main(String[] args) {
            List<Integer> list = new ArrayList();
            list.add(1);
            list.add(2);
            list.add(3);
            Integer[] array = new Integer[list.size()];
            list.toArray(array);
            for (int i:array){
                System.out.print(i+" ");
            }
        }
    }

     或者

    set.toArray(new Integer[set.size()]);

    set好处是去除重复元素

  • 相关阅读:
    git(1)-git关联GitHub-windows-转载
    jenkins(4)-jenkins配置邮件通知
    jenkins(3)-linux下安装jenkins(yum install方式)
    【PAT甲级】1090 Highest Price in Supply Chain (25 分)(DFS)
    【PAT甲级】1087 All Roads Lead to Rome (30 分)(MAP【int,string】,邻接表,DFS,模拟,SPFA)
    【PAT甲级】1018 Public Bike Management (30 分)(DFS,SPFA)
    Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
    Atcoder Grand Contest 032C(欧拉回路,DFS判环)
    Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)
    Atcoder Grand Contest 031C(构造,思维,异或,DFS)
  • 原文地址:https://www.cnblogs.com/hetaoyuan/p/11236999.html
Copyright © 2011-2022 走看看