Rog*_*gue 17 java arrays collections
我运行了两个测试用例(多次),似乎迭代地向我的列表添加值比使用更快 addAll
String[] rawArgs = new String[]{"one", "two", "three", "four", "five"};
// More efficient - 894 ns
List<String> list = new ArrayList<>();
for (String s : rawArgs) {
list.add(s);
}
// Less efficient - 1340 ns
List<String> list = new ArrayList<>();
list.addAll(Arrays.asList(rawArgs));
Run Code Online (Sandbox Code Playgroud)
我通过我的IDE以及其他人获得笔记,后一种方法是将数组转换为该数据结构的"正确"方式.但如果它实际上比第一个慢,那么有什么优势(一些模糊的类型安全?),我应该使用第二个?
编辑 - 代码基准测试:
预热JVM,首先重新创建主类对象:
public static void main(String[] args) {
Internet test;
for (int i = 0; i < 15; i++) {
test = new Internet(); // JVM warmup
}
test = new Internet();
test.printOutput();
}
Run Code Online (Sandbox Code Playgroud)
我只是在操作的两端采用纳米级系统:
start = System.nanoTime();
/* function */
end = System.nanoTime();
result = end - start;
Run Code Online (Sandbox Code Playgroud)
在测试用例中,每个开始/结束都有单独的字段,并且在操作后计算结果(在运行测试之前,JVM也通过循环实例预先加热预热).
编辑2 - 使用更大的集合进行基准测试
经过一些测试(使用Integer而不是手写所有数字),看起来更大的集合确实更慢:
有100个数字:
First operation: 18759ns
Second operation: 2680ns
Total operation: 21439ns
Run Code Online (Sandbox Code Playgroud)
Lou*_*man 18
for-each循环解析为相当于
for (int i = 0; i < rawArgs.length; i++) {
list.add(rawArgs[i]);
}
Run Code Online (Sandbox Code Playgroud)
...而ArrayList.addAll实际调用的实现toArray(),所以它最终调用Arrays.asList(rawArgs).toArray(),这使得冗余副本.也就是说,它也做了一个System.arraycopy,它可能最终使它比for循环更快 - 它可以采用任何一种方式,并且根据一些其他基准测试,它实际上可能在不同的上下文中有所不同.
该Collections.addAll(Collection<E>, E...)静态方法实际上是旨在解决这一具体问题,并快于addAll(Arrays.asList)),在其Javadoc中明确说明.
我认为Collection.addAll()至少有两个原因更快:
对于 ArrayList
ensureCapacityInternal(size + numNew);如此,如果添加的List很大,并且在手动添加中它将被多次调用,但在这种情况下,它将被调用一次,具有必要的容量.System.arraycopy(a, 0, elementData, size, numNew);复制方法,这是一种原生的高性能方法.这是一个基准测试,数组中的元素略多。结果清楚地表明该addAll方法以微弱优势获胜:
public static void main(String[] args) {
String[] rawArgs = new String[]{"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five",
"one", "two", "three", "four", "five"};
/******** WARM UP JVM *********/
for (int i = 0; i < 1000; ++i) {
arrayToListLoop(rawArgs);
}
for (int i = 0; i < 1000; ++i) {
arrayToListAddAll(rawArgs);
}
/** Actual measurement **/
long start = System.nanoTime();
for (int i = 0; i < 1000; ++i) {
arrayToListLoop(rawArgs);
}
long end = System.nanoTime();
System.out.println((end - start) / 1000);
start = System.nanoTime();
for (int i = 0; i < 1000; ++i) {
arrayToListAddAll(rawArgs);
}
end = System.nanoTime();
System.out.println((end - start) / 1000);
}
public static void arrayToListLoop(String[] arr) {
List<String> list = new ArrayList<>();
for (String s : arr) {
list.add(s);
}
}
public static void arrayToListAddAll(String[] arr) {
List<String> list = new ArrayList<>();
list.addAll(Arrays.asList(arr));
}
Run Code Online (Sandbox Code Playgroud)
结果:
1 首次运行:
2280
812
Run Code Online (Sandbox Code Playgroud)
2 次运行:
1336
613
Run Code Online (Sandbox Code Playgroud)
3 第三次运行:
2088
751
Run Code Online (Sandbox Code Playgroud)