क्या लूप और फॉर-प्रत्येक लूप के बीच एक प्रदर्शन अंतर है?


184

क्या, यदि कोई हो, तो निम्नलिखित दो छोरों के बीच प्रदर्शन अंतर है?

for (Object o: objectArrayList) {
    o.DoSomething();
}

तथा

for (int i=0; i<objectArrayList.size(); i++) {
    objectArrayList.get(i).DoSomething();
}

@ केपरो: यह एक "प्रत्येक" लूप के लिए "फॉर-इन" लूप नहीं है
एंडी टर्नर

जावा में इसका "प्रत्येक के लिए" कहा जाता है, लेकिन जब इसका उद्देश्य "इन" लूप में आता है।
दमिठ


लूप प्रदर्शन के लिए विस्तारित चर्चा यहां की गई है: stackoverflow.com/questions/12155987/…
शाम 6:08

यहां तक ​​कि अगर कोई अंतर होता है, तो यह इतना मामूली होगा कि आपको पठनीयता का पक्ष रखना चाहिए जब तक कि इस कोड के टुकड़े को प्रति सेकंड खरबों बार निष्पादित नहीं किया जाता है। और फिर आपको समय से पहले अनुकूलन से बचने के लिए एक उचित बेंचमार्क की आवश्यकता होगी।
ज़बुज़ार्ड

जवाबों:


212

जोशुआ बलोच द्वारा प्रभावी जावा में आइटम 46 से :

1.5 रिलीज में पेश किए गए प्रत्येक लूप को पूरी तरह से इट्रेटर या इंडेक्स वेरिएबल को छिपाकर अव्यवस्था और त्रुटि के अवसर से छुटकारा मिलता है। परिणामी मुहावरे संग्रह और सरणियों पर समान रूप से लागू होते हैं:

// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
    doSomething(e);
}

जब आप कोलन देखते हैं (:), इसे "इन" के रूप में पढ़ें। इस प्रकार, उपरोक्त लूप "तत्वों में प्रत्येक तत्व ई के लिए" के रूप में पढ़ता है। ध्यान दें कि प्रत्येक लूप का उपयोग करने के लिए कोई प्रदर्शन जुर्माना नहीं है, यहां तक ​​कि सरणियों के लिए भी। वास्तव में, यह कुछ परिस्थितियों में लूप के लिए एक साधारण से अधिक मामूली प्रदर्शन लाभ प्रदान कर सकता है, क्योंकि यह केवल एक बार सरणी सूचकांक की सीमा की गणना करता है। जब आप इसे हाथ से कर सकते हैं (आइटम 45), प्रोग्रामर हमेशा ऐसा नहीं करते हैं।


48
वर्थ उल्लेख करते हुए कि प्रत्येक लूप में एक इंडेक्स काउंटर तक पहुँचने का कोई तरीका नहीं है (क्योंकि यह मौजूद नहीं है)
बेज़ेज़ेरो

हां, लेकिन यह काउंटर अब लूप के बाहर दिखाई दे रहा है। ज़रूर, यह एक साधारण तय है, लेकिन प्रत्येक के लिए है!
इंडोलिंग

74
इसमें पुनरावृत्‍ति को आवंटित करने का प्रदर्शन दंड है। एंड्रॉइड लाइव वॉलपेपर में मेरे पास कुछ अत्यधिक समानांतर कोड थे। मैंने देखा कि कचरा उठाने वाला पागल हो रहा था। ऐसा इसलिए था क्योंकि प्रत्येक लूप कई अलग-अलग (अल्पकालिक) थ्रेड्स में अस्थायी पुनरावृत्तियों को आवंटित कर रहा था, जिससे कचरा कलेक्टर बहुत काम करता है। नियमित सूचकांक आधारित छोरों पर स्विच करने से समस्या ठीक हो गई।
gsingh2011

1
@ gsingh2011 लेकिन यह इस बात पर भी निर्भर करता है कि आप रैंडम एक्सेस लिस्ट का उपयोग कर रहे हैं या नहीं। गैर-यादृच्छिक अभिगम सूचियों के लिए सूचकांक आधारित पहुंच का उपयोग करना यादृच्छिक अभिगम सूचियों के लिए प्रत्येक का उपयोग करने से बहुत खराब होगा, मुझे लगता है। यदि आप इंटरफ़ेस सूची के साथ काम कर रहे हैं और इस प्रकार आपको वास्तविक कार्यान्वयन प्रकार का पता नहीं है, तो आप जाँच सकते हैं कि क्या सूची (लागू) रैंडम एसेट का
puce

3
@ gsingh2011 एंड्रॉइड डॉक्स ( developer.android.com/training/articles/perf-tips.html#Loops ) उल्लेख करते हैं कि आपको केवल ArrayList पर फॉर्च्यूनर का उपयोग करने पर प्रदर्शन जुर्माना होगा, अन्य संग्रह नहीं। मैं उत्सुक हूं कि क्या आपका मामला था।
वक्री

29

ये सभी लूप ठीक वैसा ही करते हैं, मैं सिर्फ अपने दो सेंट में फेंकने से पहले ये दिखाना चाहता हूं।

सबसे पहले, सूची के माध्यम से पाशन का क्लासिक तरीका:

for (int i=0; i < strings.size(); i++) { /* do something using strings.get(i) */ }

दूसरा, पसंदीदा तरीका चूंकि यह कम त्रुटि वाला है (आपने कितनी बार "उफ़, इन चरणों में लूप्स में i और j को मिलाया है?"

for (String s : strings) { /* do something using s */ }

तीसरा, लूप के लिए माइक्रो-ऑप्टिमाइज़्ड:

int size = strings.size();
for (int i = -1; ++i < size;) { /* do something using strings.get(i) */ }

अब वास्तविक दो सेंट: कम से कम जब मैं इनका परीक्षण कर रहा था, तो तीसरा सबसे तेज़ था जब मिलीसेकंड की गिनती करते हुए, यह बताता था कि एक सरल ऑपरेशन के साथ प्रत्येक प्रकार के लूप में कितना समय लगा, कुछ मिलियन बार दोहराया - यह जावा 5 का उपयोग कर रहा था Windows में jre1.6u10 के साथ अगर कोई दिलचस्पी रखता है।

हालांकि यह कम से कम ऐसा प्रतीत होता है कि तीसरा सबसे तेज़ है, आपको वास्तव में अपने आप से पूछना चाहिए कि क्या आप अपने लूपिंग कोड में इस पीपल के अनुकूलन को हर जगह लागू करने का जोखिम उठाना चाहते हैं क्योंकि मैंने जो देखा है, उससे वास्तविक लूपिंग है ' टी आमतौर पर किसी भी वास्तविक कार्यक्रम का सबसे अधिक समय लेने वाला हिस्सा (या शायद मैं सिर्फ गलत क्षेत्र पर काम कर रहा हूं, जो जानता है)। और जैसा कि मैंने जावा के लिए प्रत्येक लूप के बहाने उल्लेख किया है (कुछ इसे Iterator लूप के रूप में संदर्भित करता है और अन्य को फॉर-इन लूप के रूप में ) आप इसका उपयोग करते समय उस विशेष बेवकूफ बग को हिट करने की कम संभावना रखते हैं। और बहस करने से पहले कि यह कैसे अन्य लोगों की तुलना में भी तेज हो सकता है, याद रखें कि javac बिल्टकोड को बिल्कुल भी अनुकूलित नहीं करता है (ठीक है, लगभग सभी पर), यह बस इसे संकलित करता है।

यदि आप हालांकि माइक्रो-ऑप्टिमाइज़ेशन में हैं और / या आपका सॉफ़्टवेयर पुनरावर्ती लूप का बहुत उपयोग करता है और ऐसे में आपको तीसरे लूप प्रकार में रुचि हो सकती है। बस अपने सॉफ़्टवेयर को अच्छी तरह से बेंचमार्क करने से पहले याद रखें कि लूप के लिए बदलने से पहले और बाद में आपको इस विषम, सूक्ष्म-अनुकूलित एक को बदलना होगा।


5
कृपया ध्यान दें कि ++ आई <= आकार के साथ लूप के लिए "1-आधारित" है, उदाहरण के लिए लूप के अंदर गेट-विधि को 1, 2, 3, आदि के मूल्यों के लिए कहा जाएगा
वॉली

15
माइक्रो-अनुकूलित लूप लिखने का एक बेहतर तरीका है (int i = 0, size = strings.size (); ++ i <= size;) {} यह बेहतर है क्योंकि यह आकार के दायरे को कम करता है
Dónal

1
पहला तत्व लंघन के माध्यम से पहली बार i = 1 से तीसरा शुरू नहीं होता है। और यह लूप के लिए अनावश्यक है। int n = strings.length; जबकि (n -> 0) {System.out.println ("" + n + "" + तार [n]); }
लस्सी किन्नुएन

1
@ दूनल कि लूप पैटर्न पहले वाले को याद करता है और एक IOOBE देता है। यह एक काम करता है: (int i = -1, size = list.size (); ++ i <size;)
Nathan Adams

1
"ये सभी लूप ठीक वही करते हैं" गलत है। एक यादृच्छिक पहुँच का उपयोग करता है get(int), दूसरा उपयोग करता है Iterator। इस बात पर विचार करें LinkedListकि for(int i=0;i<strings.size();i++) { /* do something using strings.get(i) */ }ऐसा करने के बाद से कहीं अधिक बुरा प्रदर्शन हो रहा है get(int)
स्टीव कू

13

प्रत्येक लूप के लिए आमतौर पर पसंद किया जाना चाहिए। "प्राप्त" दृष्टिकोण धीमा हो सकता है यदि आपके द्वारा उपयोग की जा रही सूची कार्यान्वयन यादृच्छिक पहुँच का समर्थन नहीं करता है। उदाहरण के लिए, यदि एक लिंक्डलिस्ट का उपयोग किया जाता है, तो आप एक ट्रैवर्सल लागत का अनुमान लगा सकते हैं, जबकि फॉर-एप्रोच दृष्टिकोण का उपयोग करता है जो सूची में अपनी स्थिति का ट्रैक रखता है। प्रत्येक लूप की बारीकियों के बारे में अधिक जानकारी ।

मुझे लगता है कि लेख अब यहां है: नया स्थान

यहां दिखाया गया लिंक मृत था।


12

खैर, प्रदर्शन प्रभाव ज्यादातर महत्वहीन है, लेकिन शून्य नहीं है। यदि आप RandomAccessइंटरफ़ेस के JavaDoc को देखते हैं :

अंगूठे के एक नियम के रूप में, एक सूची कार्यान्वयन को इस इंटरफ़ेस को लागू करना चाहिए यदि, वर्ग के विशिष्ट उदाहरणों के लिए, यह लूप:

for (int i=0, n=list.size(); i < n; i++)
    list.get(i);

इस लूप से तेज चलता है:

for (Iterator i=list.iterator(); i.hasNext();)
      i.next();

और प्रत्येक लूप के लिए पुनरावृत्ति के साथ संस्करण का उपयोग किया जाता है, इसलिए ArrayListउदाहरण के लिए, प्रत्येक लूप सबसे तेज़ नहीं है।


वास्तव में प्रत्येक? एक सरणी के साथ भी? मैं यहां पढ़ता हूं stackoverflow.com/questions/1006395/… कि इसमें एक पुनरावृत्ति शामिल नहीं है।
ओंद्रा kaižka 22

@ Ondra loopižka: फॉर-लूप Iterables पर लूपिंग करते समय पुनरावृत्तियों का उपयोग करता है , लेकिन सरणियाँ नहीं। सरणियों के लिए एक इंडेक्स चर के साथ एक लूप का उपयोग किया जाता है। इस बारे में जेएलएस में जानकारी है ।
लीई

हाँ, तो आपको पहले इसे ऐरे के साथ एक सरणी में बनाने की आवश्यकता होगी, जिसमें एक लागत होगी।
लस्सी किन्नुंन

6

दुर्भाग्य से एक अंतर प्रतीत होता है।

यदि आप दोनों प्रकार के छोरों के लिए उत्पन्न बाइट्स कोड को देखते हैं, तो वे अलग हैं।

यहाँ Log4j स्रोत कोड से एक उदाहरण है।

/Log4j-api/src/main/java/org/apache/log/log4j/MarkerManager.java में हमारे पास एक स्थिर आंतरिक वर्ग है जिसे Log4jMarker कहा जाता है जो परिभाषित करता है:

    /*
     * Called from add while synchronized.
     */
    private static boolean contains(final Marker parent, final Marker... localParents) {
        //noinspection ForLoopReplaceableByForEach
        for (final Marker marker : localParents) {
            if (marker == parent) {
                return true;
            }
        }
        return false;
    }

मानक लूप के साथ:

  private static boolean contains(org.apache.logging.log4j.Marker, org.apache.logging.log4j.Marker...);
    Code:
       0: iconst_0
       1: istore_2
       2: aload_1
       3: arraylength
       4: istore_3
       5: iload_2
       6: iload_3
       7: if_icmpge     29
      10: aload_1
      11: iload_2
      12: aaload
      13: astore        4
      15: aload         4
      17: aload_0
      18: if_acmpne     23
      21: iconst_1
      22: ireturn
      23: iinc          2, 1
      26: goto          5
      29: iconst_0
      30: ireturn

प्रत्येक के लिए:

  private static boolean contains(org.apache.logging.log4j.Marker, org.apache.logging.log4j.Marker...);
    Code:
       0: aload_1
       1: astore_2
       2: aload_2
       3: arraylength
       4: istore_3
       5: iconst_0
       6: istore        4
       8: iload         4
      10: iload_3
      11: if_icmpge     34
      14: aload_2
      15: iload         4
      17: aaload
      18: astore        5
      20: aload         5
      22: aload_0
      23: if_acmpne     28
      26: iconst_1
      27: ireturn
      28: iinc          4, 1
      31: goto          8
      34: iconst_0
      35: ireturn

THAT Oracle के साथ क्या हो रहा है?

मैंने इसे विंडोज 7 पर जावा 7 और 8 के साथ आज़माया है।


7
उन लोगों के लिए जो डिस्सैम्ड पढ़ने की कोशिश कर रहे हैं, शुद्ध परिणाम यह है कि लूप के अंदर उत्पन्न कोड समान है, लेकिन फॉर-प्रत्येक सेटअप ने दूसरे तर्क के संदर्भ में एक अतिरिक्त अस्थायी चर बनाया है। यदि अतिरिक्त छिपे हुए चर की गणना की जाती है, लेकिन पैरामीटर खुद कोड पीढ़ी के दौरान नहीं है, तो प्रत्येक के लिए तेज होगा; यदि पैरामीटर को (;) उदाहरण में एनरजिस्ट किया गया है, तो निष्पादन समय समान होगा। होगा बेंचमार्क?
रॉबिन डेविस

4

इंडेक्सिंग के बजाय इट्रेटर का उपयोग करना हमेशा बेहतर होता है। ऐसा इसलिए होता है क्योंकि अनुक्रमांक (कॉलिंग प्राप्त) नहीं हो सकता है, जबकि इट्रेटर सूची कार्यान्वयन के लिए सबसे अधिक अनुकूलित है। उदाहरण के लिए लिंक्डलिस्ट एक सूची है, लेकिन इसके तत्वों के माध्यम से अनुक्रमणिका इट्रेटर का उपयोग करने की तुलना में धीमी होगी।


10
मुझे लगता है कि ऐसी कोई बात नहीं प्रदर्शन अनुकूलन के रूप में "हमेशा" है)।
Eckes

4

foreach आपके कोड को स्पष्ट करता है और यह सामान्य रूप से बहुत मामूली गति सुधार पर पसंद किया जाता है - यदि कोई हो।

जब भी मैं एक अनुक्रमित लूप देखता हूं, तो मुझे यह सुनिश्चित करने के लिए थोड़ी देर पार्स करनी होगी कि मुझे क्या लगता है कि यह ऐसा करता है जैसे क्या यह शून्य से शुरू होता है, क्या इसमें अंतिम बिंदु आदि शामिल है या बाहर है?

मेरा ज्यादातर समय रीडिंग कोड (जो मैंने लिखा या किसी और ने लिखा है) बिताया गया लगता है और स्पष्टता हमेशा प्रदर्शन से अधिक महत्वपूर्ण होती है। इन दिनों प्रदर्शन को खारिज करना आसान है क्योंकि हॉटस्पॉट ऐसा अद्भुत काम करता है।


4

निम्नलिखित कोड:

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

interface Function<T> {
    long perform(T parameter, long x);
}

class MyArray<T> {

    T[] array;
    long x;

    public MyArray(int size, Class<T> type, long x) {
        array = (T[]) Array.newInstance(type, size);
        this.x = x;
    }

    public void forEach(Function<T> function) {
        for (T element : array) {
            x = function.perform(element, x);
        }
    }
}

class Compute {
    int factor;
    final long constant;

    public Compute(int factor, long constant) {
        this.factor = factor;
        this.constant = constant;
    }

    public long compute(long parameter, long x) {
        return x * factor + parameter + constant;
    }
}

public class Main {

    public static void main(String[] args) {
        List<Long> numbers = new ArrayList<Long>(50000000);
        for (int i = 0; i < 50000000; i++) {
            numbers.add(i * i + 5L);
        }

        long x = 234553523525L;

        long time = System.currentTimeMillis();
        for (int i = 0; i < numbers.size(); i++) {
            x += x * 7 + numbers.get(i) + 3;
        }
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(x);
        x = 0;
        time = System.currentTimeMillis();
        for (long i : numbers) {
            x += x * 7 + i + 3;
        }
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(x);
        x = 0;
        numbers = null;
        MyArray<Long> myArray = new MyArray<Long>(50000000, Long.class, 234553523525L);
        for (int i = 0; i < 50000000; i++) {
            myArray.array[i] = i * i + 3L;
        }
        time = System.currentTimeMillis();
        myArray.forEach(new Function<Long>() {

            public long perform(Long parameter, long x) {
                return x * 8 + parameter + 5L;
            }
        });
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(myArray.x);
        myArray = null;
        myArray = new MyArray<Long>(50000000, Long.class, 234553523525L);
        for (int i = 0; i < 50000000; i++) {
            myArray.array[i] = i * i + 3L;
        }
        time = System.currentTimeMillis();
        myArray.forEach(new Function<Long>() {

            public long perform(Long parameter, long x) {
                return new Compute(8, 5).compute(parameter, x);
            }
        });
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(myArray.x);
    }
}

मेरे सिस्टम पर आउटपुट के बाद देता है:

224
-699150247503735895
221
-699150247503735895
220
-699150247503735895
219
-699150247503735895

मैं OracleJDK 1.7 अपडेट 6 के साथ Ubuntu 12.10 अल्फा चला रहा हूं।

सामान्य रूप से हॉटस्पॉट में बहुत सारे अप्रत्यक्ष और सरल निरर्थक संचालन का अनुकूलन होता है, इसलिए सामान्य तौर पर आपको उनके बारे में चिंता नहीं करनी चाहिए जब तक कि उनमें से बहुत से seqence में न हों या वे भारी नस्ट हों।

दूसरी ओर, लिंक्डलिस्ट पर अनुक्रमित मिलता है, लिंक्डलिस्ट के लिए अगले पर कॉल करने की तुलना में बहुत धीमा होता है ताकि आप पुनरावृत्ति को बनाए रखते हुए उस प्रदर्शन हिट से बच सकें जब आप पुनरावृत्तियों का उपयोग करते हैं (स्पष्ट रूप से या प्रत्येक लूप में अंतर्निहित)।


3

ArrayList या वेक्टर जैसी किसी चीज़ के साथ भी, जहाँ "get" एक साधारण सरणी लुक है, दूसरे लूप में अभी भी अतिरिक्त ओवरहेड है जो पहले नहीं है। मुझे उम्मीद है कि यह पहले की तुलना में थोड़ा धीमा होगा।


पहले लूप को प्रत्येक तत्व भी प्राप्त करना होगा। यह ऐसा करने के लिए पर्दे के पीछे एक पुनरावृत्त बनाता है। वे वास्तव में बराबर हैं।
छिपकली

C के संदर्भ में सोचें, तो एक इट्रेटर सिर्फ एक पॉइंटर को बढ़ा सकता है, लेकिन एक बार हर बार पॉइंटर की चौड़ाई से i का मान गुणा करना होगा।
पॉल टॉम्बलिन

यह निर्भर करता है कि आप किस प्रकार की सूची का उपयोग करते हैं। मुझे लगता है कि आप सही हैं, हालांकि, उपयोग करना कभी तेज नहीं होगा, और कभी-कभी धीमा।
छिपकली

3

सुनिश्चित करने के लिए जानने का एकमात्र तरीका इसे बेंचमार्क करना है, और यहां तक ​​कि यह उतना सरल नहीं है जितना कि यह ध्वनि हो सकता है । JIT कंपाइलर आपके कोड के लिए बहुत ही अप्रत्याशित चीजें कर सकता है।


3

एंड्रॉइड डेवलपमेंट टीम द्वारा किए गए अंतर का एक संक्षिप्त विश्लेषण इस प्रकार है:

https://www.youtube.com/watch?v=MZOf3pOAM6A

परिणाम है कि है है एक अंतर है, और बहुत बड़ी सूची के साथ बहुत संयमित वातावरण में यह एक उल्लेखनीय अंतर हो सकता है। उनके परीक्षण में, प्रत्येक लूप के लिए दो बार लंबे समय तक लिया गया। हालाँकि, उनका परीक्षण 400,000 पूर्णांकों की सूची से अधिक था। सरणी में प्रति तत्व वास्तविक अंतर 6 माइक्रोसेकंड था । मैंने परीक्षण नहीं किया है और उन्होंने कहा नहीं है, लेकिन मैं अपेक्षा करूंगा कि यह अंतर आदिमता की बजाय वस्तुओं के उपयोग से थोड़ा बड़ा होगा, लेकिन फिर भी जब तक आप लाइब्रेरी कोड नहीं बना रहे हैं, जहां आपको पता नहीं है कि आपके द्वारा पूछे जाने का पैमाना क्या होगा। अधिक से अधिक, मुझे लगता है कि अंतर के बारे में जोर देने लायक नहीं है।


2

चर नाम से objectArrayList, मुझे लगता है कि इसका एक उदाहरण है java.util.ArrayList। उस स्थिति में, प्रदर्शन अंतर स्पष्ट नहीं होगा।

दूसरी ओर, यदि इसका उदाहरण है java.util.LinkedList, तो दूसरा दृष्टिकोण List#get(int)एक ओ (एन) ऑपरेशन के रूप में बहुत धीमा होगा ।

इसलिए पहले दृष्टिकोण को हमेशा पसंद किया जाता है जब तक कि लूप में तर्क द्वारा सूचकांक की आवश्यकता न हो।


1
1. for(Object o: objectArrayList){
    o.DoSomthing();
}
and

2. for(int i=0; i<objectArrayList.size(); i++){
    objectArrayList.get(i).DoSomthing();
}

दोनों समान है लेकिन प्रत्येक के लिए आसान और सुरक्षित प्रोग्रामिंग उपयोग के लिए, उपयोग करने के 2 तरीके में त्रुटि की संभावना है।


1

यह अजीब है कि किसी ने भी स्पष्ट रूप से उल्लेख नहीं किया है - फोरचेक मेमोरी (इट्रेटर के रूप में) आवंटित करता है, जबकि लूप के लिए एक सामान्य किसी भी मेमोरी को आवंटित नहीं करता है। एंड्रॉइड पर गेम के लिए, यह एक समस्या है, क्योंकि इसका मतलब है कि कचरा कलेक्टर समय-समय पर चलेगा। एक खेल में आप कचरा कलेक्टर को चलाने के लिए नहीं चाहते हैं ... कभी भी। तो अपने ड्रॉ (या रेंडर) विधि में फोरच लूप का उपयोग न करें।


1

स्वीकृत उत्तर प्रश्न का उत्तर देता है, इसके अलावा ArrayList के असाधारण मामले ...

चूंकि अधिकांश डेवलपर्स ArrayList पर भरोसा करते हैं (कम से कम मुझे ऐसा लगता है)

इसलिए मैं यहां सही उत्तर जोड़ने के लिए बाध्य हूं।

डेवलपर दस्तावेज़ से सीधे: -

लूप के लिए बढ़ाया (कभी-कभी "प्रत्येक के लिए" लूप के रूप में भी जाना जाता है) का उपयोग संग्रह के लिए किया जा सकता है जो Iterable इंटरफ़ेस को लागू करता है और सरणियों के लिए। संग्रह के साथ, हैनेटर () और अगले () के लिए इंटरफ़ेस कॉल करने के लिए एक इटेरेटर आवंटित किया जाता है। एक ArrayList के साथ, एक हाथ से लिखा गिनती लूप लगभग 3x तेज (जेआईटी के साथ या बिना) है, लेकिन अन्य संग्रह के लिए लूप सिंटैक्स के लिए बढ़ाया स्पष्ट इट्रेटर उपयोग के बराबर होगा।

एक सरणी के माध्यम से पुनरावृत्ति के लिए कई विकल्प हैं:

static class Foo {
    int mSplat;
}

Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}

शून्य () सबसे धीमा है, क्योंकि JIT अभी तक लूप के माध्यम से प्रत्येक पुनरावृत्ति के लिए एक बार सरणी लंबाई प्राप्त करने की लागत को दूर नहीं कर सकता है।

एक () तेज है। यह लुकअप से बचते हुए सब कुछ स्थानीय चरों में खींचता है। केवल सरणी लंबाई एक प्रदर्शन लाभ प्रदान करती है।

JIT के बिना उपकरणों के लिए दो () सबसे तेज़ है, और JIT वाले उपकरणों के लिए एक () से अप्रभेद्य है। यह जावा प्रोग्रामिंग भाषा के संस्करण 1.5 में पेश किए गए लूप सिंटैक्स के लिए वर्धित उपयोग करता है।

तो, आपको डिफ़ॉल्ट रूप से लूप के लिए एन्हांस किए गए का उपयोग करना चाहिए, लेकिन प्रदर्शन-महत्वपूर्ण ArrayList पुनरावृत्ति के लिए एक हाथ से लिखे गिनती किए गए लूप पर विचार करें।


-2

हां, for-eachवेरिएंट सामान्य से तेज है index-based-for-loop

for-eachसंस्करण का उपयोग करता है iterator। इसलिए ट्रैवर्सिंग सामान्य forलूप की तुलना में तेज है जो इंडेक्स आधारित है।
यह इसलिए है क्योंकि iteratorट्रैवर्सिंग के लिए अनुकूलित किया गया है, क्योंकि यह अगले तत्व से पहले और पिछले तत्व के ठीक बाद की ओर इशारा करता है । index-based-for-loopधीमे होने का एक कारण यह है कि, उसे हर बार उस तत्व की स्थिति की गणना और स्थानांतरित करना होगा जो उसके साथ नहीं है iterator


-3
public class FirstJavaProgram {

    public static void main(String[] args) 
    {
        int a[]={1,2,3,45,6,6};

// Method 1: this is simple way to print array 

        for(int i=0;i<a.length;i++) 
        { 
            System.out.print(a[i]+" ");
        }

// Method 2: Enhanced For loop

        for(int i:a)
        {
            System.out.print(i+" ");
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.