为什么Collections.addAll()比arrays.addAll()性能好?
1. Collections.addAll()比arrays.addAll()更快吗?
在《Java核心编程》这本书中,“持有对象”这一章有个地方讲到:
Collections.addAll()比arrays.addAll()方法快得多!
我们知道,Collections
是一个工具类,它提供了一组操作集合类的静态方法,包括排序、交换元素、拷贝、最大值、最小值等,使用起来非常方便。addAll()
方法就是其中之一,它用来将一组元素添到一个集合中:
List<String> arrays = new ArrayList<>(); Collections.addAll(arrays, "hello", "world");
而arrays.addAll()
方法,是List
对象的一个方法,它实现的功能与Collections.addAll()
类似,也是将一组元素添加到数组中:
List<String> arrays = new ArrayList<>(); arrays.addAll(Arrays.asList("hello", "world"));
2. 是不是真的更快?
尽信书不如无书,书上虽然是这样说的,那是不是真的Collections.addAll()
比arrays.addAll()
性能好很多呢?我们不妨来测试一下:
public class Test { public static void main(String[] args) { //循环次数 int count = 100000000; System.out.println("Collections.addAll()耗时:" + collectionsTest(count) + "ms"); System.out.println("arrays.addAll()耗时:" + arraysTest(count) + "ms"); } public static long collectionsTest(int count) { long startTime = System.currentTimeMillis(); for (int i = 0; i < count; i++) { List<String> arrays = new ArrayList<>(); Collections.addAll(arrays, "hello", "world"); } return System.currentTimeMillis() - startTime; } public static long arraysTest(int count) { long startTime = System.currentTimeMillis(); for (int i = 0; i < count; i++) { List<String> arrays = new ArrayList<>(); arrays.addAll(Arrays.asList("hello", "world")); } return System.currentTimeMillis() - startTime; } }
我们使用这两个方法,向其中添加元素,分别循环一个小目标,得出耗时对比:
arrays.addAll()耗时:3324ms
Collections.addAll()耗时:2034ms可以看到,这两个方法的耗时差距还是很大的,
arrays.addAll()
的耗时大概是Collections.addAll()
的1.6倍左右。看来Bruce Eckel没有骗我,他是个诚实的人,说的确实对。
3. 为什么它这么快?
好了,是不是的问题已经解决了,我们已经知道,Collections.addAll()
确实比arrays.addAll()
方法快很多,可是:
Why?
让我们回过头来再看一眼刚才的代码,首先是Collections.addAll()
:
List<String> arrays = new ArrayList<>(); Collections.addAll(arrays, "hello", "world");
public static <T> boolean addAll(Collection<? super T> c, T... elements) { boolean result = false; for (T element : elements) result |= c.add(element); return result; }
这两行代码很简单,就做了两件事情:
- 创建
arrays
- 调用
addAll()
- 使用
数组迭代器
,将元素添加到arrays
中
然后是arrays.addAll()
:
List<String> arrays = new ArrayList<>(); arrays.addAll(Arrays.asList("hello", "world"));
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; }
它做了什么呢?可以看到:
- 创建
arrays
- 使用
Arrays.asList()
新创建了一个集合 - 调用
addAll()
- 使用
c.toArray()
方法复制入参到a
中。(耗时较长) - 使用
ensureCapacityInternal()
校验是否溢出 - 使用
System.arraycopy()
拷贝a
中新传入的元素到数组容器elementData
中
综上所述,可以得出,Collections.addAll()
和arrays.addAll()
主要有两种差别:
-
arrays.addAll()
方法会在调用前使用Arrays.asList()
多创建一个集合 - 在两个
addAll()
方法内部,arrays.addAll()
会比Collections.addAll()
多一些集合创建,数组长度校验的操作。
因此,大家在开发过程中,还是尽量使用Collections.addAll()
,可以获得更好的性能。
原文地址:https://segmentfault.com/a/1190000022182433
相关推荐
-
MyBatis增强工具pndao-帮你自动写SQL Java基础
2020-7-7
-
《Netkiller Java 手札》· 二进制文件操作大全 Java基础
2020-5-30
-
浅层次了解Java中的String Java基础
2020-6-15
-
你不知道Lambda的秘密和陷阱 Java基础
2020-5-28
-
这样终止线程,竟然会导致服务宕机? Java基础
2020-6-15
-
面试必备:Java线程池解析 Java基础
2019-9-4
-
红黑树插入操作的java实现 Java基础
2018-12-9
-
捋一捋JavaScript对象的继承 Java基础
2020-5-29
-
图的理解:基本概念 Java基础
2018-12-8
-
如何画出一张合格的技术架构图? Java基础
2020-5-28