关注“Java技术迷”升职加薪不脱发!

在日常开发过程中,数组转List的使用频率非常之高。大家可以回想一下,通常你都是怎么转的呢?

用代码说话,下面来看一段代码:

public class Test {    public static void main(String[] args) {        List list= Arrays.asList("hello","world");        System.out.println(list.remove("hello"));    }}

先自己想想这段代码有没有问题,使用

List list= Arrays.asList("hello","world");

来创建一个List,然后再使用remove将其移除。从逻辑上来说,确实没毛病,也有很多人认为这本来就没问题。下面我们来运行一下上面这段代码,结果:

很多人估计都不敢相信自己的眼睛,上面这段代码居然会报错。

如果我们把上面这段代码改一下:

public class Test {    public static void main(String[] args) {        List list= new ArrayList<>();        list.add("hello");        list.add("world");        System.out.println(list.remove("hello"));    }}

运行结果:

true

奇了怪了吧,这就没问题了。

我们来看看

Arrays.asList("hello");

这个asList方法到底干了些什么?

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

粗略的看了一下,他返回的不就是ArrayList对象吗?下面这段代码也是new一个ArrayList对象。

List list= new ArrayList<>();

为什么上面那段就不行呢?整个java.util.Arrays.ArrayList类有哪些方法

他居然是Arrays的一个静态内部类。现在可以确认这个

java.util.Arrays.ArrayListjava.util.ArrayList不是同一个。

重点来了,这个静态内部类里有个final修饰的数组:

private final E[] a;

final修饰变量表示此变量是不可修改的。也就是我们上面的remove为什么报错的原因。居然是因为这个Arrays中的ArrayList中使用的是一个固定大小的数据来存储数据的,同理我们也可以推断,不能使用add方法,下面我来试试add方法就知道了。

public class Test {    public static void main(String[] args) {        List list= Arrays.asList("hello","world");        System.out.println(list.add("!"));    }}

运行结果:

运行结果和我们预期的是一样的。

另外我们看看java.util.ArrayList源码:

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {    private static final long serialVersionUID = 8683452581122892189L;

    /**     * Default initial capacity.     */    private static final int DEFAULT_CAPACITY = 10;    private static final Object[] EMPTY_ELEMENTDATA = {};    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};    transient Object[] elementData;

这段代码有也有个数组用来保存数据:

 transient Object[] elementData;

人家不是使用final修饰,transient修饰只是和系列化有关系。所以人家java.util.ArrayList是不会报异常的。

上面Arrays.ArrayList中居然没有add和remove方法。认真的你会发现,它也继承了AbstractList。进去看看她的源码:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {

    protected AbstractList() {    }

    //这是前面我们使用过,并且抛异常的方法    public boolean add(E e) {        add(size(), e);        return true;    }     //上面的add方法调用的是这个方法    public void add(int index, E element) {        //抛异常        throw new UnsupportedOperationException();    }

    public E remove(int index) {        //抛异常        throw new UnsupportedOperationException();    }    //其他代码省略

}

前面已经把java.util.Arrays.ArrayList的方法都看过了,并没有add和remove,也就是说他没实现父类的add和remove两个方法。那就是调用了AbstractList的方法了,所以上面抛的两个异常是在这里抛出来的。

相反java.util.ArrayList却老老实实的两个方法都实现了。

    public boolean add(E e) {        ensureCapacityInternal(size + 1);  // Increments modCount!!        elementData[size++] = e;        return true;    }     public E remove(int index) {        rangeCheck(index);

        modCount++;        E oldValue = elementData(index);

        int numMoved = size - index - 1;        if (numMoved > 0)            System.arraycopy(elementData, index+1, elementData, index,                             numMoved);        elementData[--size] = null; // clear to let GC do its work

        return oldValue;    }

好了,上面问题已经得出了答案。下面来说说应该如何正确使用数组转List。

正确的姿势

倒也不是说List list= Arrays.asList("hello");这个不要用,只是你得搞清楚原理,一不小心就会为别人(也可能是自己)留下

方式一:

String[] strings = {"hello", "world"};List list = new ArrayList(Arrays.asList(strings));

方式二(推荐):

 String[] strings = {"hello", "world"}; List list = new ArrayList<>(strings.length); Collections.addAll(list, strings);

方式三:

原始的方法就是变量数组,然后new 对象ArrayList,遍历数组,一个一个add进去,这里就不贴代码了,这是最笨的办法。

总结

  1. Arrays.asList(strArray)方式将数组转换为List后,不能增删改原数组的值,仅作读取使用;

  2. ArrayList构造器方式,在List的数据量不大的情况下,可以使用;

  3. 集合工具类Collections.addAll(),在List的数据量巨大的情况下,优先使用,可以提高操作速度。

  4. 不仅是ArrayList,其余List的子类(LinkList/Vector)也可以用同样的方法实现数组和集合转变。

推荐阅读  点击标题可跳转IDEA 上位?不!Eclipse Theia 1.0 发布!Fastjson到了说再见的时候了JDK15正式发布,划时代的ZGC同时宣布转正看完本文有收获?请转发分享给更多人

关注「Java技术迷」,提升Java技

java list 转数组_数组转List,一定要小心这个坑!相关推荐

  1. arrays中copyof复制两个数组_数组,及二维数组

    1.1 命令行参数(C) 在程序运行过程中,可以向应用程序传递一些参数,这些参数称为命名行参数. public 命令行参数以字符串的形式传入args数组中.可以一次传递0-多个参数,以空格分割. 如果 ...

  2. 扩容是元素还是数组_数组是如何随机访问元素?数组下标为什么从0开始,而不是1?...

    作者:鹏磊 来源:搜云库技术团队 数组如何实现随机访问元素 什么是数组? 数组(Array)是一种线性表数据结构,它用一组连续的内存空间,来存储相同类型的数据. 什么是线性表(Linear List) ...

  3. c字符串分割成数组_数组与字符串

    定义数组时,应该注意以下几点: (1) 数组使用的是方括号[ ],不要误写成小括号( ). (2) 常量表达式的值必须是一个正整数值,不能含有变量,但是可以是符号常数或常量表达式. (3) 数组定义后 ...

  4. pycharm定义空的二维数组_数组与面向对象

    数组与面向对象 数组 一维数组 数组:[ ] 存储相同类型的多个数据 变量:单个数据 数组:多个数据 数组的特点: 引用数据类型 数据是个容器,长度一旦确定不可改变 一个数组中存放的多个数据的类型要求 ...

  5. java中int边界值_数组中重复的数字2019.12.06

    记录一下,记录一下,记录一下,因为我的记忆好像只有10s 题目描述: 在一个长度为n的数组里面,所有元素的范围是[0,n-1],数组中可能存在某些数字是重复的,请判断是否有重复元素,如果有,找出来. ...

  6. java环形数组_数组实现环形队列Java

    用数组实现环形队列的特点是高效. 能快速判断队列是否 满/空: 能快速存取数据. 因为简单高效,所以甚至在硬件中都实现了环形队列. 环形队列广泛应用于网络数据的收发,和不同应用间数据交换(内核和应用程 ...

  7. java随机数去重排序_数组去重及排序/0~10随机数字/字符串中出现最多的字符及次数...

    数组去重及排序: var arr = [1,5,1,2,6,8,1,81,9,0]; for(var i=0;i for(var j=i+1;j if(arr[i] == arr[j]){ arr.s ...

  8. c#json对象转数组_数组和对象的区别

    数组和对象两者都可以用来表示数据的集合,曾一度搞不清楚"数组"(array)和"对象"(object)的根本区别在哪里. 有一个数组a=[1,2,3,4],还有 ...

  9. 转为字符数组_数组的20种常用的方法?

    1.shift 删除数组中的第一个元素 2.pop 删除数组中的最后一个元素 3.unshift 增加元素在数组的前面 4.push 增加元素在数组的后面 5.map 循环,并且返回新的数组 6.fo ...

最新文章

  1. 学习ui设计的流程是什么
  2. 互联网人的求生战役!分享身边的 5 个故事
  3. 通用的异步处理类和进度通知类及其示例
  4. mybatis处理集合、循环、数组和in等语句的使用
  5. python中scale_Python中的Log-scale mathplotlib?
  6. mysql5.7 备份恢复_RDS for MySQL 5.7 备份恢复为本地实例-阿里云开发者社区
  7. 接口测试基础与工具(一)
  8. sharp s2 android 9,夏普s2第三方ROM AOSP(Android P)v105
  9. beyond 注册表删除
  10. userdel: user user is currently used by process 18752解决办法
  11. vos3000配置与通讯测试(一)
  12. 鸿蒙系统诞生的背景,为何国产系统发展多年无人问津,华为鸿蒙系统刚一开始就引起轰动...
  13. 【统计学习方法】第10章 隐马尔可夫模型
  14. PROE5.0飞利浦耳机结构设计教程
  15. SpringBoot+Vue项目实现高校学生健康打卡系统
  16. 图书管理系统-数据库设计
  17. 电磁场与仿真软件(18)
  18. 【27】unet网络复现及学习(1)
  19. unc0ver更新适用于iOS14的越狱工具
  20. 32位全彩色与24位全彩色有啥区别

热门文章

  1. 抚摸那条船——彭晓东
  2. 最值反演[PKUWC2018][loj2542]随机游走
  3. protobuf入门教程(三):常用序列化/反序列化接口
  4. Zookeeper 安装和配置---学习二
  5. 【项目介绍】协程——C语言实现的用户态非抢占式轻量级线程
  6. 分布式一致性算法Raft简介(下)
  7. Linux 写时复制机制原理
  8. 25个实用编程小技巧
  9. 【线上分享】云游戏面对低延迟挑战的实践
  10. Netflix:我们是如何评估Codec性能的?