2010-04-07 126 views
59

ArrayList中的toArray方法,Bloch使用System.arraycopy和Arrays.copyOf來複制數組。什麼更有效率:System.arraycopy vs Arrays.copyOf?

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; 
} 

如何比較這兩種複製方式,何時使用哪種?

+1

什麼是 「布洛赫」?爲什麼代碼片段相關? – 2015-05-02 13:56:23

+2

@Ciro Bloch是編寫ArrayList實現的人。 – Insomniac 2015-06-04 23:33:14

+0

另請參見:https://stackoverflow.com/q/44487304/14955 – Thilo 2017-06-12 03:14:39

回答

86

區別在於Arrays.copyOf不僅複製元素,它還創建一個新的數組。 System.arrayCopy複製到現有陣列中。

以下是Arrays.copyOf的來源,因爲您可以看到它在內部使用System.arraycopy來填充新陣列。

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { 
    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; 
} 
+1

它顯而易見.... Arrays.copyOf應創建一個新的實例因爲我們沒有傳遞給它;而我們將目標傳遞給System.arraycopy。關於速度,顯然System.arraycopy應該贏得,因爲它是一個本地方法,並最終Arrays.copyOf也調用這個方法來複制一個數組。 – 2016-07-24 14:58:42

+2

Java源代碼[無所謂](https://stackoverflow.com/questions/44487304/why-arrays-copyof-is-2-times-faster-than-system-arraycopy-for-small-arrays#comment75970318_44487304 ),因爲內在是創建的。 – maaartinus 2017-06-11 20:10:02

11

System.arrayCopy要快得多。它在系統中,因爲它使用Java land之外的直接內存拷貝。儘可能使用它。

+1

但System.arraycopy只複製到現有數組中。 Arrays.copyOf也爲你創建輸出數組。 – Thilo 2010-04-07 03:24:56

+2

這是真的,只要你在封面下使用System.arraycopy,你使用的任何便利包裝只是肉汁。 – 2010-04-07 13:28:51

+4

而且,有些情況下'System.arrayCopy' *不能*使用直接內存拷貝。 – 2011-11-22 09:29:02

3

System.arrayCopy本地實現,因此將比任何Java代碼更快。我建議你使用它。

+4

僅僅因爲它通過JNI使用本地代碼,並不意味着它會更快:http://www.javaspecialists.eu/archive/Issue124.html – Dag 2012-11-27 17:26:54

31

雖然System.arraycopy是本地實現的,因此可能會比一個Java循環快,它並不總是一樣快,你可能期望。考慮下面這個例子:

Object[] foo = new Object[]{...}; 
String[] bar = new String[foo.length]; 

System.arraycopy(foo, 0, bar, 0, bar.length); 

在這種情況下,foobar陣列的基本類型有不同的基本類型,所以arraycopy的實現必須檢查複製每一個引用的類型,以確保它實際上是對String實例的引用。這比數組內容的簡單C風格memcopy慢得多。

的另一點是,Arrays.copyOf使用System.arraycopy引擎蓋下,所以節省您創建一個新的陣列,通過arraycopy將微乎其微自己加油吧實現。假設這就是你想要做的...

我的建議是使用的版本,使您的代碼最容易閱讀,只擔心哪一個更快,如果分析告訴你,它很重要。


1 - 它可能更快,但它是也可以的JIT編譯器優化手工代碼迴路是沒有區別的這麼好的工作。

+1

+1用於指出有時需要進行的類型檢查。 – Thilo 2010-04-07 06:43:31

+0

@StephenC,關於你的第一段,是否有情況下'System.arrayCopy'實際上可能*較慢*? – Pacerier 2014-08-18 02:50:01

+0

@Prier - 我不知道任何。但這不是不可能的。 – 2014-08-18 05:28:09

12

如果你想要一個數組的精確複印件(比方說,如果你想要做一個防守副本),複製數組的最有效的辦法可能是使用數組對象的clone()方法:

class C { 
    private int[] arr; 
    public C(int[] values){ 
     this.arr = values.clone(); 
    } 
} 

我並沒有打算測試它的性能,但它是一個非常快的機會,因爲它都是本機的(調用中分配和複製),而克隆是一種特殊的JVM祝福的複製對象的方式(其他用途主要是邪惡的),並且可能會採取一些「捷徑」。

就個人而言,如果它比任何其他複製方式都慢,我仍然會使用clone,因爲它更容易閱讀,幾乎不可能在寫入時搞砸。 System.arrayCopy,另一方面...

+1

對,但'System.arrayCopy'也是原生的(它專用於該任務),而'clone'似乎必須處理很多*條件* ... – Pacerier 2014-08-18 02:55:28

+0

@Pacerier「我不經常使用'克隆「......但是當我這樣做時,我在陣列上使用它。」 – gustafc 2014-08-18 07:16:44

+0

我在談論* * .clone()'當在數組上使用時....無論如何,它仍然會返回一個Object,然後它必須被轉換回數組(=額外的工作)。 – Pacerier 2014-08-18 07:27:50

10

你看過Sun的Arrays.copyOf()的實現嗎?

public static int[] copyOf(int[] original, int newLength) { 
    int[] copy = new int[newLength]; 
    System.arraycopy(original, 0, copy, 0, 
        Math.min(original.length, newLength)); 
    return copy; 
} 

可以看出,它採用System.arraycopy()內部,這樣的表現是相同的。

0
 class ArrayCopyDemo { 
    public static void main(String[] args) { 
    char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 
      'i', 'n', 'a', 't', 'e', 'd' }; 
    char[] copyTo = new char[7]; 

    System.arraycopy(copyFrom, 2, copyTo, 0, 7); 
    System.out.println(new String(copyTo)); 
} 
} 
0

而不是辯論,這些是實際結果。顯然,您的選擇取決於您想要複製多少數據。

字節[]複製性能試驗

10,000,000迭代40B array.copyOfRange:135ms systems.arraycopy:141ms

10,000,000迭代1000B array.copyOfRange:1861ms systems.arraycopy:2211ms

10,000,000迭代4000b array.copyOfRange:6315ms systems.arraycopy:5251ms

百萬迭代10萬桶 array.copyOfRange:15,198ms systems.arraycopy:14783ms

相關問題