搞清楚 Java 中 List 的 toArray 方法
AI量子速读
GPT-4
生成中. . .
介绍自己
相关文章推荐
生成文章简介
矩阵穿梭
本文目的是从源码层面分清楚 List
中这两个函数的区别:
Object[] toArray()
<T> T[] toArray(T[] a)
。参数a
由用户传递,用于指定新数组生成的位置。
快速感知
两个函数的作用都是将 ArrayList
对象转换为数组,都返回新数组,多次运行 toArray
方法会获得不同的数组对象,但是这些数组对象中内容一样的。
区别在于是否携带参数。具体区别:
Object[] toArray()
中- 如果
ArrayList
中的内容是基本类型,你可以简单的认为新数组之间没有任何关联。 - 如果
ArrayList
中的内容是自定义类型,那么即使toArray
返回不同的新数组,但是在不同的新数组中,对应下标元素均引用同一个对象。
- 如果
java
1 | // 自定义类型 |
<T> T[] toArray(T[] a)
,a
指的是用户可以指定的新数组的存储位置,返回类型为T[]
。如果用户给的a
足够大,代码就会把元素复制到a
中,如果还有富余,则结尾设置null
;如果不够大,则代码自己生成一个大小刚好符合要求的新的数组,再复制返回。ls.toArray(new Object[0])
等同于ls.toArray()
阿里巴巴 Java 开发手册对集合使用的相关要求
一、(六)9.【强制】 使用集合转数组的方法, 必须使用集合的 toArray(T[] array)
, 传入的是类型完全一致、 长度为 0 的空数组。
原因:
- 直接使用
toArray
无参方法存在问题, 此方法返回值只能是Object[]
类, 若强转其它类型数组将出现ClassCastException
错误。 - 使用 toArray 带参方法, 数组空间大小的
length
的选择:- 等于 0, 动态创建与
size
相同的数组, 性能最好。 - 大于 0 但小于
size
, 重新创建大小等于size
的数组, 增加 GC 负担。也就是说,作为参数传入的那个数组没用上。 - 等于
size
, 在高并发情况下, 数组创建完成之后,size
正在变大的情况下, 负面影响与第 2 种情况相同。但实际上,并发场景本就不建议使用ArrayList
。 - 大于
size
, 空间浪费, 且在size
处插入null
值, 存在 NPE 隐患。
- 等于 0, 动态创建与
源码阅读
此部分需读者耐心阅读。
System.arraycopy()
和 Arrays.copyOf()
方法
为了便于后面内容的理解,这里先介绍 System.arraycopy()
和 Arrays.copyOf()
方法。
java
1 | /** System |
使用示例:
java
1 | public static void main(String[] args) { |
Arrays.copyOf()
返回一个全新数组。
java
1 | // Arrays.copyOf() 的其中两个重写 |
ArrayList
类中的 toArray
java
1 | // ArrayList 类 |
【拓展】使用原有 Collection
类构造新的 ArrayList
java
1 | private static final Object[] EMPTY_ELEMENTDATA = {}; |
小结:
- 如果传入的集合类
c
大小为空,则元素列表elementData
设为空集合。 - 如果传入的集合类
c
大小不为空,则将c
中的数组处理好。
本文参考
- ArrayList 源码分析 | JavaGuide
- 深入理解List的toArray()无参方法和带参方法-CSDN博客
- 阿里巴巴 Java 开发手册(黄山版)
推荐阅读:一个 Bug JDK 居然改了十年?
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 半方池水半方田!
评论