java集合转数组避坑指南

本文探讨了Java中从数组转换到List的两种常见方法,对比了直接使用Arrays.asList()与通过ArrayList构造函数的方式。文章深入分析了直接使用asList()方法可能导致的UnsupportedOperationException异常原因,并推荐了更安全可靠的转换方法。

一般来说常见的有两种转换方式(更推荐后者)

 String[] a = { "小龙虾", "的", "呆毛"};
 List<String> myList = Arrays.asList(a);
String[] myArray = { "小龙虾", "的", "呆毛" };
List<String> myList = new ArrayList<String>(Arrays.asList(myArray));

asList中的参数必须为包装类数组,而不能是基本数据类型数组。
请注意:一般情况下推荐使用原始数据类型数组而不是装箱后的原始数据类型列表
总结为:包装类数组比基本数据类型数组多耗费8倍的内存。

但是阿里巴巴手册上强制要求POJO类属性必须使用包装器类型:
在这里插入图片描述
个人理解:int score:假如score并没有值,没有参加这个考试,这个值在类中会被默认初始化为0,分数为0明显不符合逻辑。
如果是Integer score;可以设置为null,表示这个值为空,而不是0。

普通转换

 String[] a = { "小龙虾", "的", "呆毛"};
 List<String> myList = Arrays.asList(a);

但是若加上以下语句

myList.add("233");

则会报错,报错信息为

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)

嗯?为什么报错调用AbstractList.add()呢?
我们暂且保留这一疑惑,先去看一下AbstractList.add()为什么会报错

public boolean add(E e) {
    add(size(), e);
    return true;
}
...
public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

这就很疑惑了,为什么AbstractList中的add方法要抛出一个异常呢?
其实源代码中的注释已经说明了这一切。

* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} unless
* {@link #add(int, Object) add(int, E)} is overridden.

原来是要我们重写add这一方法,若不重写,直接抛出异常。
接下来我们去探究为什么会调用AbstractList.add()。
我们去查看一下Array.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")
    public <T> T[] toArray(T[] a) {
       //省略
    }

    @Override
    public E get(int index) {
        return a[index];
    }

    @Override
    public E set(int index, E element) {
      //省略
    }

    @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) {
       //太长不看
    }

原来上面这种方式返回的ArrayList是Arrays的静态内部类。
而里面并没有重写add()。
又因为和这个内部类继承了AbstractList,所以此处会调用AbstractList.add(),然后抛出UnsupportedOperationException异常。
Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。

更好的转换

String[] myArray = { "小龙虾", "的", "呆毛" };
List<String> myList = new ArrayList<String>(Arrays.asList(myArray));
myList.add("233");
System.out.println(myList.toString());

这种转换方式可以调用
调用的是:

public ArrayList(Collection<? extends E> c)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值