考慮下面的代碼:Collection.toArray()VS Collection.stream()指定者()
List<String> myList = Arrays.asList(1, 2, 3);
String[] myArray1 = myList.toArray(new String[myList.size()]);
String[] myArray2 = myList.stream().toArray(String[]::new);
assert Arrays.equals(myArray1, myArray2);
在我看來,使用一個流簡單得多。
因此,我測試了每個的速度。
List<String> myList = Arrays.asList("1", "2", "3");
double start;
start = System.currentTimeMillis();
for (int i = 0; i < 10_000_000; i++) {
String[] myArray1 = myList.toArray(new String[myList.size()]);
assert myArray1.length == 3;
}
System.out.println(System.currentTimeMillis() - start);
start = System.currentTimeMillis();
for (int i = 0; i < 10_000_000; i++) {
String[] myArray2 = myList.stream().toArray(String[]::new);
assert myArray2.length == 3;
}
System.out.println(System.currentTimeMillis() - start);
結果是使用流大約慢了四倍。在我的機器上,816ms(流)vs 187ms(無流)。我也嘗試切換周圍的時間語句(myArray1之前的myArray2),這對結果影響不大。爲什麼這麼慢?創建一個Stream
如此計算密集?
我跟着@霍爾格的意見,並研究了JVM上測試了一下(當然還不夠),閱讀this post,this article,this article,並使用JMH。
結果(經由JMH):
StreamToArrayArrayListBenchmark.testMethod avgt 5 2846.346 32.500±納秒/運算
private static final List<String> myList = IntStream.range(1, 1000).mapToObj(String::valueOf).collect(Collectors.toList());
@Benchmark
public void testMethod() {
String[] myArray = myArrayList.toArray(new String[0]);
}
ToArrayEmptyArrayListBenchmark.testMethod avgt 5 1417.474 ±20.725 ns/op
private static final List<String> myList = IntStream.range(1, 1000).mapToObj(String::valueOf).collect(Collectors.toList());
@Benchmark
public void testMethod() {
String[] myArray = myArrayList.toArray(new String[myList.size()]);
}
ToArraySizedArrayListBenchmark.testMethod avgt 5 1853.622±178.351納秒/運算
private static final List<String> myList = new LinkedList<>(IntStream.range(1, 1000).mapToObj(String::valueOf).collect(Collectors.toList()));
@Benchmark
public void testMethod() {
String[] myArray = myArrayList.stream().toArray(String[]::new);
}
StreamToArrayLinkedListBenchmark.testMethod avgt 5 4152.003±59.281納秒/運算
private static final List<String> myList = new LinkedList<>(IntStream.range(1, 1000).mapToObj(String::valueOf).collect(Collectors.toList()));
@Benchmark
public void testMethod() {
String[] myArray = myArrayList.toArray(new String[0]);
}
ToArrayEmptyLinkedListBenchmark.testMethod avgt 5 4089.550±29.880納秒/運算
private static final List<String> myList = new LinkedList<>(IntStream.range(1, 1000).mapToObj(String::valueOf).collect(Collectors.toList()));
@Benchmark
public void testMethod() {
String[] myArray = myArrayList.toArray(new String[myList.size()]);
}
ToArraySizedArrayListBenchmark.testMethod avgt 5 4115.557±93.964納秒/運算
總結:
| ArrayList | LinkedList
stream | 2846 | 4152
toArray sized | 1853 | 4115
toArray empty | 1417 | 4089
使用江鈴控股有限公司(可能天真地),我仍然看到ArrayList::toArray
大約快兩倍Stream::toArray
。然而,這似乎是因爲ArrayList
只是做陣列拷貝的能力,就像@Andreas指出的那樣,因爲當源是LinkedList
時,結果大致相等。
瞭解myList.toArray(new String[0])
絕對很好。
如果使用Arrays.stream(),該怎麼辦? –
@JoshLee在我的真實代碼中,我有一個List,我試圖將其轉換爲數組。我不是如何使用Arrays.stream()? – dantiston
@Holger你是否認爲這是重複的,我的結論是錯誤的?我並沒有真的在詢問如何做基準 - 我假設我的基準不是100%準確的。我真的在問'流'的開銷 - 這在另一個問題中沒有涉及。 – dantiston