Arrays.asList(...)得到的ArrayList对象,调用addAll方法,抛出java.lang.UnsupportedOperationException

零、动机

1、刷力扣时,89. 格雷编码

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> res = Arrays.asList(0, 1);
        for (int i = 2; i <= n; i++) {
           List<Integer> tmp = new LinkedList<>(); 
           int sum = (int)Math.pow(2, i - 1);
           for (Integer num : res)  {
               tmp.add(0, num + sum);
           }
           res.addAll(tmp); // 抛出java.lang.UnsupportedOperationException
        }
        return res;
    }
}

2、更好的写法

class Solution {
    public List<Integer> grayCode(int n) {
        List<Integer> res = new ArrayList<>(Arrays.asList(0, 1));
        for (int i = 2; i <= n; i++) {
           int sum = (int)Math.pow(2, i - 1);
           for (int j = res.size() - 1; j >= 0; j--) {
               res.add(sum + res.get(j));
           }
        }
        return res;
    }
}

思路:

  • n = 2时,有00, 01, 11, 10。
  • n = 3时,显然,需要增加值>=4的若干个数,又要保证相邻两个间恰有1位不同,那直接在n = 2的基础上,每个数加4就好了啊。也就是100, 101, 111, 110。
  • 最后只要保证首尾也是恰有1位不同即可:00, 01, 11, 10, 110, 111, 101, 100。(对[100, 101, 111, 110],倒置为[110, 111, 101, 100]即可)。

一、demo

public class Test52 {
    public static void main(String[] args) {
        //List<Integer> al1 = new ArrayList<>();
        //al1.add(1);
        //al1.add(2);
        //al1.add(3);
        List<Integer> al1 = Arrays.asList(1, 2, 3);
        List<Integer> al2 = new LinkedList<>();
        al2.add(4);
        al2.add(5);
        al2.add(6);
        al1.addAll(al2);
        System.out.println(al1);
    }
}
/*
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
	at com.forrest.test.Test52.main(Test52.java:24)
*/

二、原因剖析

1、Arrays.asList()的源码

   public static <T> List<T> asList(T... a) {
       return new ArrayList<>(a);
   }
  • 乍一看返回的是ArrayList对象,执行addAll方法不应该有错啊。
  • 但实际上,上述的ArrayList是Arrays类的内部类。
private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {}
  • 而这个ArrayList没有重写AbstractList类的add方法,导致抛出java.lang.UnsupportedOperationException。
// AbstractList类
public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

2、调用过程

(0)Arrays类中的ArrayList的类图
在这里插入图片描述
(1)al1.addAll(al2); ,执行的addAll方法的源码:

// AbstractCollection类
public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

(2)执行add的源码

// AbstractList类
public boolean add(E e) {
   add(size(), e);
   return true;
}

(3)执行add(size(), e);的源码

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

三、解决办法

1、为啥java.util.ArrayList的addAll方法可以呢?

// java.util.ArrayList重写了addAll方法
public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}

2、因此转为java.util.ArrayList对象即可

public class Test52 {
    public static void main(String[] args) {
        List<Integer> al1 = new ArrayList<>(Arrays.asList(1, 2, 3));
        List<Integer> al2 = new LinkedList<>();
        al2.add(4);
        al2.add(5);
        al2.add(6);
        al1.addAll(al2);
        System.out.println(al1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值