UnsupportedOperationException之数组和List集合之间的转换

标题
数组和List集合之间的转换

前言:本文介绍数组和list集合之间的转换,通过源码的形式解释各种方法的优劣,通过阅读本篇文章,在实际开发避免步入坑中。

一、数组转List

以此数组为例:
String []str={"abc","def","123"};

1. 方法一、使用for循环将数组元素添加到list集合中

        List<String> list=new ArrayList<>(str.length);
        for(String str1:str){
            list.add(str1);
        }
        System.out.println(list.toString());//输出[abc, def, 123]

  此例采用传统的for循环遍历,可以明显看到,使用for循环遍历,并且且需要一个一个添加到集合中,对于数据量大的数组来说,非常耗时,并不推荐使用。

2. 方法二、使用Arrays.asList()方法(慎用)

        list= Arrays.asList(str);
        //list.remove(0);  此处将抛出UnsupportedOperationException异常
        //list.add("add");  此处将抛出UnsupportedOperationException异常
        System.out.println(list.toString());//输出[abc, def, 123]
        str[2]="update";  //修改数组的元素会影响list集合
        System.out.println(list.toString());//输出[abc, def, update]
        list.set(2,"asList");//修改list集合的元素会影响数组的内容
        System.out.println(list.toString());//输出[abc, def, asList]

  此方法将数组转换List后,不能对List增删,只能查改,否则将抛出异常,下来我们来看下一源码是如何实现的:

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
    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);
        }
		//此处省略size()  方法
		//此处省略 toArray()  方法
		//此处省略 get()  方法
		//此处省略 set()  方法
		//此处省略 indexOf()  方法
		//此处省略 contains()  方法
		//此处省略 spliterator()  方法
		//此处省略 forEach()  方法
		//此处省略 replaceAll()  方法
		//此处省略 sort()  方法
    }

  通过源码我们可以看到Arrays.asList()方法返回是私有静态内部类java.util.Arrays.ArrayList,并不是java.util.ArrayList类,该内部类继承自AbstractList类,仅有重写set、get方法等,并没有重写add、remove方法,所以很好的解释为什么我们在返回的list中调用add和remove方法抛出异常了。

3. 使用ArrayList的构造方法

        List<String> list2=new ArrayList<>(Arrays.asList(str1));
        System.out.println(list2.toString());//输出[abc, def, 123]

  通过此构造方法我们可以得到一个list集合,仅仅适用于数据量小的时候采用。

4. 使用Collections.addAll() [官方推荐使用的方法]

        List<String> list3=new ArrayList<>(str1.length);
        Collections.addAll(list3,str1);
        System.out.println(list3.toString());//输出[abc, def, 123]

& & Collections.addAll()方法,将数组中的元素转为二进制,然后添加到List中,这是最高效的方法(底层次用的是位运算)。源码如下:

    public static <T> boolean addAll(Collection<? super T> c, T... elements) {
        boolean result = false;
        for (T element : elements)
            result |= c.add(element);
        return result;
    }

5. jdk1.8新增使用Arrays的stream

        List<String> list4 = Arrays.stream(str1).collect(Collectors.toList());
        System.out.println(list4);//输出[abc, def, 123]

  此方法是jdk1.8之后新增的通过stream流的方式来进行转换。

6. jdk1.9使用List.of(),返回的是*【不可变的】*

List<String> list3=List.of(str);

  使用前提:当集合中存储的元素个数已经确定,不再改变。此方法为 Java9新增方法,定义在List接口内,并且为静态方法,故可以由类名直接调用。

7. 方式七:使用CollectionUtils.arrayToList()

        List<String> list5= CollectionUtils.arrayToList(str1);
        System.out.println(list5);
补充一点:当我们使用Arrays.asList()进行转换时,数组的类型引用类型的。
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

  该方法参数是一个泛型T类型的,且返回的类型也是带有泛型的,因此就可以解释,数组的类型为什么必须是引用类型的,因为泛型必须是引用类型的。

二、List转数组

以此集合为例进行说明

        List<String> list=new ArrayList();
        list.add("123");
        list.add("abc");
        list.add("456");
        String[] array = new String[list.size()];

1. 方式一、使用for循环得到数组

        for(int i = 0; i < list.size();i++){
            array[i] = list.get(i);
        }
        System.out.println(Arrays.toString(array));

2. 方式二、使用带参的toArray()方法

        list.toArray(array);//
        System.out.println(Arrays.toString(array));

3. 方式三、使用stream流

        array= (String[]) list.stream().toArray();
补充一点:使用无参数toArray()方法
        array=(String[])list.toArray();
        System.out.println(Arrays.toString(array));//抛出ClassCastException异常

  使用无参方法返回的是Object类型的,在java中子类的引用不能指向父类或其它子类对象,就算强转也会导致运行失败并抛出ClassCastException;
源码public Object[] toArray() { return Arrays.copyOf(elementData, size); }
  如果使用该方法我们可以通过循环的方式将Object类型的数组复制给String类型的数组

        Object[] element = list.toArray();
        System.out.println(Arrays.toString(element));//输出[123, abc, def]


        for (int i = 0; i < element.length; i++) {
            array[i] = (String) element[i];
        }
        System.out.println(Arrays.toString(array));//输出[123, abc, def]

完结。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值