本文是对Arrays.asList()方法从源码角度进行分析,解析使用中的一些困惑。

首先看Arrays.asList()的源码

public static <T> List<T> asList(T... a) {  
    return new ArrayList<T>(a);  

使用该方法 可以将一个变长参数或者数组转换成List
看似很简单但实际使用起来却会发现存在很多问题,看下面代码来发现问题。

先来看第一个问题,基本类型数组作为参数问题。

public class ArraysAsListTest {
    
    public static void main(String[] args) {
        
        int[] a = {1,2,3};
        Integer[] b = {1,2,3};
        
        List listA = Arrays.asList(a);
        List listA1 = Arrays.asList(1,2,3);
        List listB = Arrays.asList(b);
        
        System.out.println(listA.size());//out:1
        System.out.println(listA1.size());//out:3
        System.out.println(listB.size());//out:3
    }
}
嗯?用int类型的数组作为参数为什么输出size是1呢,使用Integer类型size就是3了呢。
再看源码,asList接收的是一个泛型变长参数,而我们知道基本类型是不能泛型化的,就是说8种基本类型不能作为泛型参数,要想作为泛型参数就要使用其所对应的包装类。

但是listA的Size为什么是1呢,这是因为listA传递的是一个int类型的数组,数组是一个对象,它是可以泛型化的,也就是说例子中是把一个int类型的数组作为了T的类型,所以转换后在List中就只有一个类型为int数组的元素。后边ListA1与ListB也就可以理解了,一个是进行了自动打包,一个是本来就是包装类型。

我们可以打印下list中元素类型进行验证

System.out.println("ListA元素类型:"+listA.get(0).getClass());
        //out:ListA元素类型:class [I
        System.out.println("ListA元素:"+Arrays.toString((int[]) listA.get(0)));
        //ListA元素:[1, 2, 3] 该处是为了验证list中元素
        System.out.println("ListA1元素类型:"+listA1.get(0).getClass());
        //out:ListA1元素类型:class java.lang.Integer
        System.out.println("ListB元素类型:"+listB.get(0).getClass());
        //out:ListB元素类型:class java.lang.Integer

接下来看第二个问题asList()方法返回对象使用add()方法抛出异常,还是先看代码

public class ArraysAsListTest {
    
    public static void main(String[] args) {
        List<String> pets = Arrays.asList("cat","dog");
        pets.add("what");
    }
}
异常:
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(Unknown Source)
    at java.util.AbstractList.add(Unknown Source)
    at ArraysAsListTest.main(ArraysAsListTest.java:9)

What?一个List执行add方法会抛出异常,难道add方法不是List的基本用法吗。还是来研究下asList的实现吧

查看一下Arrays.asList中使用的ArrayList到底长啥样?

原来Arrays的asList方法使用的ArrayList类是一个内部定义的类,而不是java.util.ArrayList类。看其部分源码

public class Arrays {  
    .......  
  
    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) {  
            if (array==null)  
            throw new NullPointerException();  
            a = array;  
        }  
          
        ......  
    }  
}

这个静态内部类,存储数组元素的a变量是final类型的,由此判断,这个静态内部类是不能做任何内部元素的添加删除操作的!就跟String类一样,String对象存储字符数组的变量也是有final修饰符的。因为一旦增加数组元素,这个数组容量已经定好的容器就无法装载增加的元素了。

内部类里面并没有add,remove方法,可以看下这个类继承的AbstractList类里面对这些方法的实现

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {  
    ........  
  
    public void add(int index, E element) {  
        throw new UnsupportedOperationException();  
    }  
  
    public E remove(int index) {  
        throw new UnsupportedOperationException();  
    }  
}

Ok!找到异常的来源了,我们使用asList得到的对象add、remove方法直接就是抛出异常

如果要对asList得到的对象使用add、remove方法可以使用如下解决办法

List<String> pets = new ArrayList<String>(Arrays.asList("a", "b", "c")); 
那么再来看最后一个问题,上代码

public class ArraysAsListTest {
    
    public static void main(String[] args) {
        String[] test = {"a","b","c","d","e"};
        List<String> testList = Arrays.asList(test);
        System.out.println("list原始顺序:"+testList);
        //洗牌打乱list中元素顺序 使用Collections.shuffled方法
        Collections.shuffle(testList, new Random(2));
        System.out.println("list打乱后顺序:"+testList);
        //list顺序打乱后 原数组会发生神马???
        System.out.println("list打乱顺序后数组内容:"+Arrays.toString(test));
        /*
         *     list原始顺序:[a, b, c, d, e]
            list打乱后顺序:[e, a, c, b, d]
            list打乱顺序后数组内容:[e, a, c, b, d]
         */
        
    }
}

哦,NO!!!我只是改变list的顺序,然而数组顺序却也发生了变化,很多时候这并不是我们想要的。

这时候我们就要意识到Arrays.asList()产生的list对象会使用底层数组作为其物理实现,只要执行操作修改这个list就会修改原来的数组。要想不改变原来数组,就要在另一个容器中创建一个副本,写法如下

List<String> testList = new ArrayList<String>(Arrays.asList(test));

Arrays.asList()需要注意的坑相关推荐

  1. Java集合工具类的一些坑,Arrays.asList()、Collection.toArray()...

    Arrays.asList() 使用指南 最近使用Arrays.asList()遇到了一些坑,然后在网上看到这篇文章:Java Array to List Examples 感觉挺不错的,但是还不是特 ...

  2. java stream toarray_Java集合工具类的一些坑,Arrays.asList()、Collection.toArray()...

    Arrays.asList() 使用指南 最近使用Arrays.asList()遇到了一些坑,然后在网上看到这篇文章:Java Array to List Examples 感觉挺不错的,但是还不是特 ...

  3. 通过Arrays.asList数组转为集合的坑

    首先定义一个int类型的数组 int[] arr = {1,2,3};// 将数组转为集合并输出List<int[]> ints = Arrays.asList(arr);System.o ...

  4. 使用Arrays.asList、ArrayList的subList时,你有踩过这些坑吗?

    前沿技术早知道,弯道超车有希望 积累超车资本,从关注DD开始 作者:申城异乡人, 图文编辑:xj 来源:https://blog.csdn.net/zwwhnly/article/details/10 ...

  5. Arrays.asList()避坑指南

    1. Arrays.asList() 该方法是将数组转化成List集合的方法. List<String> list = Arrays.asList("a"," ...

  6. Arrays.asList()的坑

    Arrays.asList()产生的ArrayList并不是集合包下的的ArrayList,而是实现在Arrays类中的内部类ArrayList,该类并未重写remove()方法,因此Arrays.a ...

  7. java 是否含有日文_Java踩坑记系列之Arrays.asList

    阅读本文大概需要6分钟 1. java.util.Arrays.asList()可以方便的把一个数组转成ArrayList集合来使用,但是如果对集合使用增加或删除元素的操作将会报错,如下: List ...

  8. 【Java】Arrays.asList 有坑

    1.概述 阿里巴巴Java开发规范说到使用工具类Arrays.asList()方法把数组转换成集合时,不能使用其修改集合相关的方法. 因为它的add/remove/clear方法会抛出Unsuppor ...

  9. Java Arrays.asList注意事项

    Arrays.asList用来将数组转化为List,这个看似功能很明了的方法却暗藏玄机. 请先看下面的程序: int[] datas = new int[]{1,2,3,4,5}; List list ...

最新文章

  1. DDD领域驱动实践记录
  2. 雷鸟邮件查找所有星标邮件_雷鸟的4种轻量级电子邮件替代品
  3. 数学图形(1.34) peut aussi曲线
  4. Linux驱动的ioctl函数简要说明
  5. 【OpenCV学习笔记】【函数学习】七(改变图像尺寸)
  6. Windows Server 2008 多元密码策略之ADSIEDIT篇
  7. STM32外部中断具体解释
  8. 海康威视摄像头使用:iVMS-4200 VS客户端
  9. python数据挖掘项目——航空公司客户价值分析(详解)
  10. MSP430的AD7705驱动程序
  11. 华为S5700交换机端口聚合
  12. 关于WGAN的学习总结——Lipschitz约束与正则化
  13. 通过CSS代码判断浏览器方法大全
  14. Github详细教程
  15. java-通知-阿里云短信服务
  16. idea解决快捷键冲突,自定义快捷键,常用快捷键
  17. HTTP下载文件校验失败原因分析与解决
  18. 【STM32单片机-库函数】继电器——relay
  19. gis可达性分析步骤_CYD软件技能 | 城市动态设计分析制图 Design for the Urban Dynamics...
  20. Oracle: Ignore 参数在Oracle 的Exp/imp的意义

热门文章

  1. autocad.net 画多段线_解决AutoCAD2014绘制多段线的详细教程--系统之家
  2. mysql日期函数,时间函数大全
  3. 汇编——数组字的传输
  4. oppo锁频段_oppo手机这些隐藏功能,你可能不知道!
  5. RPC和GRPC和Http
  6. 我的合租生活1----忍无可忍就无须再忍
  7. C++Primer11.3.2
  8. echarts雷达图鼠标悬浮显示单轴数据
  9. vb.net 教程 4-7 文本文件编码 2
  10. Microsoft Project 2013 安装失败的解决方案