Array 和 List 都是我们在开发过程中常见的数据结构。我们都知道 Array 是定长的,List 是可变长。而且,List 的实现类 ArrayList 也是根据 Array 去实现的。

以下 Array 指代数组,List 指代数组列表。

Array 转 List

当然最原始的方法就是使用遍历的方式,将 Array 中的元素都添加到 List 中。这种实现方式这里不作赘述。

Java1.2 之后,Jdk 语言提供 Arrays 这个工具类。大大简化了我们常见的 Array 操作,但是也有不少需要注意的问题。

如下:

Integer[] a = { 1, 2 };
List<Integer> l = Arrays.asList(a);

这是我们常见的 Array 转换 List 的方式,但是这个使用上有一个问题。当对 List 对象 l 进行列表插入操作时:

l.add(3);

程序就会抛出异常 java.lang.UnsupportedOperationException。这是为什么呢?

查看 Arrays.asList 源码发现,

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

这里返回的 ArrayList 并不是 java.util.ArrayList 而是 java.util.Arrays.ArrayList。Arrays 又新建了一个 ArrayList 内部类,实现了一些基本 get set 方法。

回头查看 java.util.Arrays.ArrayList.ArrayList(E[] array) 构造函数,

ArrayList(E[] array) {a = Objects.requireNonNull(array);
}

不难发现,java.util.Arrays.ArrayList 虽然打着 List 的旗号,继承了 AbstractList 。但是其只是在 Array 的基础上进行了简单的封转,AbstractList 中则是直接重写了 add 方法,表示这个方法是不允许操作。

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

明白了这个错误产生的原因,回头想一下 Java 的这些开发者们为什么这样设计。

ArrayList 中如果要添加一个元素,则需要先对其内部的 Array 进行扩容,然后将 Old Array 复制到扩容后的 New Array 中。如果 Array 转 List 仅仅是读取操作,或是在 Array 的 Size 范围之内进行替换操作,再将 Array 复制一遍,不免会对内存进行浪费,倒不如直接将原始的 Array 直接拿来维护更为直接和高效(正如java.util.Arrays.ArrayList的实现方式)。

明白这个缘由之后,如果要在 Array 转 List 之后,不只有只读操作,那么则需要下面的实现,

List<Integer> l = new ArrayList<>(Arrays.asList(a));

虽然在我们日常的开发过程中,已经习惯了使用 ArrayList 去代替 Array,但是了解此处 Java 的转换过程还是能够让我们少踩坑。

List 转 Array

因为 Array 的长度不可变,所以这个转换过程中,会有长度不匹配的情况。

常见的转换方法是 ArrayList.toArray()ArrayList.toArray(T[])

这两个实现的共同点是都是对 ArrayList 中的 Array 进行 Copy 操作,生成一个新的数组返回。不同点是前者返回值是 Object[],后者是 T[]

ArrayList.toArray(T[]) 的使用过程中需要注意,当要转换的 Array 长度小于 ArrayList 的 size 时,不要试图通过传入形参的方式进行转换,虽然这在 Array 的长度大于 List 时不会出现问题。

如下代码:

// l [1, 2, 3]
Integer[] a = new Integer[2];
l.toArray(a); // error 正确写法:a = l.toArray(a);
Stream.of(a).forEach(System.out::println);

输出结果是:null null

查看源码实现:

public <T> T[] toArray(T[] a) {if (a.length < size)// Make a new array of a's runtime type, but my contents:return (T[]) Arrays.copyOf(elementData, size, a.getClass());System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;
}// Arrays.copyOf
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;
}

可见,当 a.length < size 成立,入参 a 并没有被使用,所以 a 依然是 new Integer[2]

所以,极度建议在转换之前初始化 Array 的长度为 ArrayList 的 size,并且使用返回值重新给 Array 赋值。

// l [1, 2, 3]
Integer[] b = new Integer[l.size()];
b = l.toArray(b);
Stream.of(b).forEach(System.out::println);

备注

部分内容参考:《码出高效:Java开发手册》 一书。

原文地址

Array 和 List 的转换问题相关推荐

  1. Java 集合 --- Array和List互相转换

    Java 集合 --- Array和List互相转换 List 转 Array Array 转 List 包装类数组和基本类型数组互相转换 List 转 Array 使用toArray方法只能返回 O ...

  2. python中List类型与numpy.array类型的互相转换

    当然要先引入numpy包 import numpy as np List转numpy.array: temp = np.array(list) numpy.array转List: arr = temp ...

  3. python中数组转矩阵_python实现矩阵和array数组之间的转换

    python 列表.矩阵.数组之间的关系 矩阵可以实现多维切片,如: b = m[1:10, 3:20] 但是 多维列表却不可以首先,没见过b = m[1:10, 3:20] 这种写法,小编试了一下有 ...

  4. java array和list互相转换

    打印 注:打印时不是地址而是值 System.out.println(Arrays.toString(nums)); 查看变量的数据类型 变量名.getClass().toString() list转 ...

  5. Python:list 和 array的对比以及转换时的注意事项

    前言 array,顾名思义,数组,就是存储数字.处理数字的一种数据结构.今天在将list转换为array时,遇到了一个问题,数据量比较大,刚开始怎么都不知道问题出在哪里.直到我用一个3*3的小数据测试 ...

  6. Array与List的转换

    1.List转为Array String[] arr = {"a","b","c"}; String[] objects = (String ...

  7. scala array和list互相转换

    array有toList方法 list有toArray方法 非常简单,方便

  8. python numpy array 数组维度转换(转维)

    在实践中,经常需要对中间数据或输出数据进行维度转换,保证多个数据间计算维度上的一致性. 一般主要涉及pytorch中tensorde的维度转换.numpy中array的维度转换.本篇先对array的维 ...

  9. Php的if自动转换类型,php之数据类型自动转换,php之数据类型转换_PHP教程

    php之数据类型自动转换,php之数据类型转换 1:概述 ---php是一种弱类型的语言,它可以根据运行环境的变化而自动进行数据类型的转换 1.1转换成布尔类型的原则 以下值都将转换成布尔类型中的fa ...

最新文章

  1. java并发核心知识体系精讲_JAVA核心知识汇总
  2. linux安装apache的纠结过程
  3. iOS之深入解析静态库和动态库
  4. MySQL高级 - 常用工具 - mysqladmin
  5. 问题 1044: [编程入门]三个字符串的排序
  6. 跟一个刚毕业不久的码农聊天后被凡尔赛了
  7. TRUNCATE恢复-bbed
  8. 华科团队发布 OVIS 遮挡视频实例分割基准数据集
  9. 前端三大框架 Vue.js、AngularJS、React 的区别
  10. CSU 1115: 最短的名字(字典树)
  11. 《统一沟通-微软-实战》-6-部署-2-中介服务器-2-安装中介服务器
  12. 原型工具Axure:常用效果制作(选中、淘宝网导航、轮播图、toast效果、呼出键盘、省市二级联动、步进器、订单详情案例、中继器)
  13. java页面标签span_span标签跳转新页面
  14. 高中计算机必修选修知识点总结,高中数学必修+选修全部知识点精华归纳总结.pdf...
  15. 怎么设置android投屏 桌面程序,手机怎么投屏到电脑?
  16. 威廉•欧奈尔选股七法
  17. DoTween常用动画效果
  18. Apple推荐的2020年最佳应用程序已经出炉
  19. php商城开发人人分销团队级差分红升级规则订制
  20. 2022年金九银十软件测试面试题大全,精心挑选常问面试题

热门文章

  1. 区块链行业的一次“里程碑时刻”…
  2. HttpUnit模拟按钮点击以及爬虫实现
  3. C++基础编程题(06)求调和平均数(两个数,的倒数平均值的倒数)
  4. android聚合天气,聚合数据Android SDK 天气查询演示示例
  5. Java bho插件,javascript-使用IE插件浏览器帮助器对象(BHO)访...
  6. 三态缓存 Tri-state buffer
  7. Maxthon插件开发
  8. html怎么设置外面有线,TP-Link路由器有线方式桥接设置图文教程
  9. 武汉大学计算机考研分析
  10. 不知不觉又到了万(wu)众(liao)期(tou)待(ding)的十一黄金周了