2010-04-07 15 views
59

ArrayList में ToArray विधि, ब्लॉच एक सरणी की प्रतिलिपि बनाने के लिए 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

"बलोच" क्या है? कोड स्निपेट प्रासंगिक क्यों है? –

+2

@Ciro Bloch वह व्यक्ति है जिसने ArrayList कार्यान्वयन लिखा था। – Insomniac

+0

यह भी देखें: https://stackoverflow.com/q/44487304/14955 – Thilo

उत्तर

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 भी एक सरणी की प्रतिलिपि बनाने के लिए इस विधि को कॉल करता है। –

+2

जावा स्रोत [इससे कोई फर्क नहीं पड़ता] (https://stackoverflow.com/questions/44487304/why-arrays-copyof-is-2-times-faster-than-system-arraycopy-for-small-arrays#comment75970318_44487304) क्योंकि आंतरिक बनाया गया था। कभी-कभी होने वाली टाइपिंग जांच को इंगित करने के लिए – maaartinus

11

System.arrayCopy बहुत तेज है। यह सिस्टम में है क्योंकि यह जावा भूमि के बाहर एक सीधी मेमोरी प्रति का उपयोग करता है। जब संभव हो तो इसका इस्तेमाल करें।

+1

लेकिन System.arraycopy केवल मौजूदा सरणी में प्रतिलिपि बनाता है। Arrays.copyOf भी आपके लिए आउटपुट सरणी बनाता है। – Thilo

+2

यह सच है, और जब तक आप कवर के तहत System.arraycopy का उपयोग कर रहे हैं, जो भी सुविधा रैपर आप उपयोग करते हैं वह सिर्फ ग्रेवी है। –

+4

और, ऐसे मामले हैं जहां 'System.arrayCopy' * प्रत्यक्ष स्मृति प्रति का उपयोग नहीं कर सकता है। –

3

System.arrayCopy मूल रूप से लागू किया गया है, और इसलिए किसी भी जावा कोड से तेज़ होगा। मैं आपको इसका इस्तेमाल करने की सलाह देता हूं।

+4

सिर्फ इसलिए कि यह जेएनआई के माध्यम से देशी कोड का उपयोग करता है, इसका मतलब यह नहीं है कि यह तेज़ होगा: http://www.javaspecialists.eu/archive/Issue124.html – Dag

31

जबकि System.arraycopy देशी रूप कार्यान्वित किया जाता है, और इसलिए एक जावा पाश से तेजी से हो सकता है, यह हमेशा के रूप में तेजी से के रूप में आप उम्मीद कर सकते नहीं है। इस उदाहरण पर विचार:

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

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

इस मामले में, foo और bar सरणियों के आधार प्रकार विभिन्न आधार प्रकार है, इसलिए arraycopy के कार्यान्वयन सुनिश्चित करें कि यह वास्तव में है बनाने के लिए की नकल की हर संदर्भ के प्रकार की जाँच करने के लिए किया एक स्ट्रिंग उदाहरण का संदर्भ। यह काफी धीमा है कि सरणी सामग्री की एक सरल सी-शैली memcopy।

अन्य मुद्दा यह है कि Arrays.copyOf हुड के नीचे System.arraycopy का उपयोग करता है, तो आप एक नई सरणी बनाने और यह अपने आप भरने arraycopy का उपयोग कर कम से कम हो जाएगा द्वारा प्राप्त की बचत। मान लीजिए कि आप यही करने की कोशिश कर रहे हैं ...

मेरी सलाह उस संस्करण का उपयोग करना होगा जो आपके कोड को पढ़ने के लिए सबसे आसान बनाता है, और केवल प्रोफाइलिंग प्रोफाइलिंग के बारे में बताता है कि यह महत्वपूर्ण है।


1 - यह तेजी से हो सकता है, लेकिन यह भी संभव है कि JIT कम्पाइलर एक हाथ से कोड पाश के अनुकूलन कोई अंतर नहीं है कि वहाँ इस तरह के एक अच्छा काम करता है।

+1

+1। – Thilo

+0

@StephenC, आपके पहले पैराग्राफ के संबंध में, ऐसे मामले हैं जहां 'System.arrayCopy' वास्तव में धीमा * हो सकता है? – Pacerier

+0

@Pacerier - मुझे किसी के बारे में पता नहीं है। लेकिन यह असंभव नहीं है। –

12

आप एक सटीक एक सरणी की प्रतिलिपि चाहते हैं (जैसे कि, आप एक रक्षात्मक नकल करना चाहते हैं) शायद सरणी वस्तु की clone() विधि का उपयोग कर रहा है एक सरणी को कॉपी करने की सबसे प्रभावी तरीका है,:

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

मुझे इसके प्रदर्शन की जांच करने के लिए परेशान नहीं है, लेकिन यह बहुत तेज़ होने का एक अच्छा मौका है क्योंकि यह सभी मूल (आवंटन और कॉल में प्रतिलिपि) है, और क्लोनिंग वस्तुओं की प्रतिलिपि बनाने का एक विशेष JVM आशीर्वाद तरीका है (और यह अन्य उद्देश्यों के लिए अधिकतर बुराई है) और कुछ "शॉर्टकट" लेने में सक्षम होने की संभावना है।

व्यक्तिगत रूप से, मैं अभी भी clone का उपयोग करता हूं अगर यह प्रतिलिपि बनाने के किसी भी अन्य तरीके से धीमा था, क्योंकि लिखना आसान है और लेखन के दौरान इसे असंभव करना असंभव है। System.arrayCopy, दूसरी तरफ ...

+1

दाएं, लेकिन 'System.arrayCopy' मूल भी है (और यह उस कार्य को समर्पित है) जबकि' क्लोन 'को कई * शर्तों * से निपटना पड़ता है ... – Pacerier

+0

@Pacerier "मैं अक्सर उपयोग नहीं करता' क्लोन' ... लेकिन जब मैं करता हूं, तो मैं इसे सरणी पर उपयोग करता हूं। " – gustafc

+0

मैं * * * .clone() 'के बारे में बात कर रहा था जब सरणी पर उपयोग किया जाता था ....किसी भी मामले में, यह अभी भी एक ऑब्जेक्ट देता है जिसे फिर एक सरणी (= अतिरिक्त कार्य) में वापस डाला जाना चाहिए। – Pacerier

10

क्या आपने सूर्य के 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

बहस के बजाय, ये वास्तविक परिणाम हैं। जाहिर है, आपकी पसंद इस बात पर निर्भर करेगी कि आप कितना डेटा कॉपी करना चाहते हैं।

बाइट [] कॉपी प्रदर्शन परीक्षण

10000000 पुनरावृत्तियों 40b array.copyOfRange: 135ms systems.arraycopy: 141ms

10000000 पुनरावृत्तियों 1000B array.copyOfRange: 1861ms systems.arraycopy: 2211ms

10,000,000 पुनरावृत्तियों 4000b array.copyOfRange: 6315ms सिस्टम.एरेकॉपी: 5251ms

1000000 पुनरावृत्तियों 100,000b array.copyOfRange: 15,198ms systems.arraycopy: 14783ms

संबंधित मुद्दे