जावा: एक संग्रह के माध्यम से पुनरावृति करने का सबसे अच्छा तरीका (यहाँ ArrayList)


98

आज मैं खुशी से कोडिंग कर रहा था जब मुझे एक कोड मिला जो मैंने पहले ही सैकड़ों बार उपयोग किया था:

एक संग्रह के माध्यम से Iterating (यहाँ ArrayList)

किसी कारण से, मैंने वास्तव में ग्रहण के स्वत: पूर्णता विकल्पों पर ध्यान दिया और मुझे आश्चर्य हुआ:

दूसरों की तुलना में निम्नलिखित छोरों का उपयोग करने के लिए कौन से मामले बेहतर हैं?

क्लासिक सरणी इंडेक्स लूप:

for (int i = 0; i < collection.length; i++) {
  type array_element = collection.get(index);
}

Iterator hasNext () / next ():

for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
  type type = (type) iterator.next();   
}

और मेरा पसंदीदा क्योंकि लिखने के लिए इतना आसान है:

for (iterable_type iterable_element : collection) {

}

2
जब यह मेरे पास आता है तो मैं ज्यादातर 3 लूप का उपयोग करता हूं।
हैरी जॉय

1
दूसरे तरीके से इसके बेहतर उपयोग के लिए:for (Iterator<type> iterator = collection.iterator(); iterator.hasNext();) { type type = iterator.next(); }
माइक जोंस

4
संग्रह इंटरफ़ेस में एक विधि "गेट" नहीं है, इसलिए पहला हमेशा संभव नहीं होता है।
thePerson

जवाबों:


104

पहले एक उपयोगी है जब आपको तत्व के सूचकांक की आवश्यकता होती है। यह मूल रूप से ArrayLists के लिए अन्य दो वेरिएंट के बराबर है , लेकिन यदि आप a का उपयोग करते हैं तो यह वास्तव में धीमा होगा LinkedList

दूसरा तब उपयोगी होता है जब आपको तत्व के सूचकांक की आवश्यकता नहीं होती है लेकिन आपको पुनरावृति करते हुए तत्वों को निकालने की आवश्यकता हो सकती है। लेकिन इससे IMO के थोड़ा बहुत क्रियाशील होने का नुकसान है।

तीसरा संस्करण मेरी पसंदीदा पसंद है। यह छोटा है और उन सभी मामलों के लिए काम करता है, जहाँ आपको किसी भी अनुक्रमणिका या अंतर्निहित इटरेटर की आवश्यकता नहीं है (अर्थात आप केवल तत्वों को एक्सेस कर रहे हैं, उन्हें हटा नहीं रहे हैं या Collectionकिसी भी तरह से संशोधित नहीं कर रहे हैं - जो कि सबसे आम मामला है)।


3
+1 यह मुझे हराया। लिंक्डलिस्ट का उल्लेख करने जा रहा था ( सभी Collection सूचकांक द्वारा पुनः प्राप्त करने के लिए सस्ते नहीं हैं)।
द स्क्रीम मीस्टर

जब तक किसी को केवल लूप तत्वों की आवश्यकता होती है, यह हमेशा 3 संस्करण का उपयोग करना अच्छा होता है, क्योंकि कार्यान्वयन पहले से ही सभी विभिन्न संग्रहों के लिए मौजूद है और हर एक के बजाय प्रदर्शन को बेहतर बनाने के लिए सूर्य या कोई भी जेडीके कार्यान्वयन प्रयास करता है।
फनी

@ फ़नी: अन्य दो वेरिएंट किसी भी JDK कार्यान्वयन पर भी काम करते हैं।
MAK

मैंने यह नहीं कहा कि वे काम नहीं करेंगे, लेकिन अगर किसी भी तरह से संग्रह के कार्यान्वयन के लिए एक निश्चित सुधार या प्रदर्शन में बदलाव किया जाता है, तो यह स्वचालित रूप से आपके कोड के लिए लागू होगा और आपको प्रदर्शन में सुधार करने के लिए लिखने की आवश्यकता नहीं है मेरा मतलब है।
फणी

1
@Phani: AFAIK 3rd फॉर्म केवल सेकेंडरी शुगर है जो दूसरे फॉर्म के लिए है (यानी हुड के तहत foreach वेरिएंट वास्तव में एक इटेरेटर का उपयोग करता है)। तो किसी भी प्रदर्शन लाभ दोनों प्रकारों के लिए उपलब्ध होना चाहिए। पाठ्यक्रम के पहले संस्करण को कोई प्रदर्शन लाभ नहीं मिलेगा (जैसे कि यदि Listइसे पेड़ के रूप में लागू किया जाता है, तो यह वास्तव में धीमा होगा)।
MAK

36

उन सभी के अपने उपयोग हैं:

  1. यदि आपके पास एक चलने योग्य है और उन सभी के लिए बिना शर्त पार करने की आवश्यकता है:

    for (iterable_type iterable_element: संग्रह)

  2. यदि आपके पास एक चलने योग्य है लेकिन सशर्त रूप से ट्रैवर्स करने की आवश्यकता है:

    के लिए (Iterator iterator = collection.iterator (); iterator.hasNext ();)

  3. यदि डेटा-संरचना इसमें लागू नहीं होती है:

    for (int i = 0; मैं <संग्रह.लिफ्ट; I ++)


क्या आप सशर्त रूप से पहली विधि को पार करने के लिए ऐसा कर सकते हैं: यदि (iterable_element.some_attribute) {// कुछ; } और {// कुछ मत करो; }। यदि हाँ तो अनिवार्य रूप से पहले और दूसरे तरीके के बीच कोई अंतर नहीं है, सिंटैक्टिक शुगर के अलावा।
थॉमस गुयेन

1 बस के रूप में दूसरों का उपयोग कर breakऔर / याcontinue
arcyqwerty

13

जावा 8 के साथ इसके अतिरिक्त संग्रह (स्ट्रीम) का उपयोग है

collection.forEach((temp) -> {
            System.out.println(temp);
});

या

collection.forEach(System.out::println);

जावा 8 स्ट्रीम के बारे में अधिक जानकारी और वंडरर्स लिंक के लिए संग्रह


4

उनमें से कोई भी दूसरों की तुलना में "बेहतर" नहीं है। तीसरा, मेरे लिए, अधिक पठनीय है, लेकिन किसी ऐसे व्यक्ति के लिए जो फोरचेस का उपयोग नहीं करता है, यह अजीब लग सकता है (वे पहले पसंद कर सकते हैं)। सभी 3 जावा को समझने वाले किसी भी व्यक्ति के लिए बहुत स्पष्ट हैं, इसलिए जो भी आपको कोड के बारे में बेहतर महसूस कराता है।

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


2

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

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

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

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

मुझे उम्मीद है यह मदद करेगा। अनुक्रमिक पहुंच सूचियों के लिए पहला विकल्प धीमा होगा।


1

यहाँ एक उदाहरण है

Query query = em.createQuery("from Student");
             java.util.List list = query.getResultList();
             for (int i = 0; i < list.size(); i++) 
             {

                 student = (Student) list.get(i);
                 System.out.println(student.id  + "  " + student.age + " " + student.name + " " + student.prenom);

             }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.