जावा में सरणी या सूची। कौन सा तेज है?


351

मुझे जावा में क्रमिक रूप से एक्सेस होने के लिए हजारों स्ट्रिंग्स को मेमोरी में रखना होगा। क्या मुझे उन्हें किसी सरणी में संग्रहीत करना चाहिए या मुझे किसी प्रकार की सूची का उपयोग करना चाहिए?

चूँकि सरणियाँ मेमोरी के एक सन्निहित भाग में सभी डेटा रखती हैं (सूचियों के विपरीत), हजारों तारों को स्टोर करने के लिए एक सरणी का उपयोग समस्याओं का कारण होगा?


5
"चूंकि सरणियाँ स्मृति के एक सन्निहित भाग में सभी डेटा को रखती हैं" क्या आपके पास जावा के लिए इसे वापस करने के लिए किसी प्रकार का उद्धरण है?
मैट बी

1
कोई मैट नहीं। मैं यह जानता हूं कि सी। के लिए मैं अनुमान लगा रहा हूं कि जावा उसी विधि का उपयोग करेगा।
युफोरिया hor

मुझे संदेह है कि यह उन्हें स्मृति के एक ही हिस्से में रखेगा।
Fortyrunner

3
यहां तक ​​कि अगर यह मेमोरी का एक ब्लॉक है, तब भी यह केवल 1000 * 4 = 4kb के आसपास होगा, जो कि बहुत सारी मेमोरी नहीं है।
CookieOfFortune

3
@mattb पूरे सीएस में 'सरणी' का मतलब है। कोई उद्धरण आवश्यक नहीं। JLS और [JVM Spec] () से लेकर सरणी लंबाई में कई संदर्भ केवल तभी समझ में आते हैं जब सरणियाँ अस्पष्ट होती हैं।
लोर्ने

जवाबों:


358

मेरा सुझाव है कि आप परीक्षण करने के लिए एक प्रोफाइलर का उपयोग करें जो तेज है।

मेरी निजी राय है कि आपको सूचियों का उपयोग करना चाहिए।

मैं एक बड़े कोडबेस पर काम करता हूं और डेवलपर्स के पिछले समूह ने हर जगह एरेज़ का इस्तेमाल किया है । इसने कोड को बहुत अनम्य बना दिया। सूची में बड़े बदलाव के बाद हमने देखा कि गति में कोई अंतर नहीं है।


2
@Fortyrunner - आपके अनुभव से, क्या अमूर्त और कच्चे डेटा रूपों के बीच जावा में ऐसे कोई विकल्प हैं जो प्रदर्शन में महत्वपूर्ण अंतर रखते हैं?
युफोरिया

4
प्रदर्शन माप के साथ समस्याओं में से एक यह है कि आपको लगातार जावा के नए संस्करणों के खिलाफ पुन: परीक्षण करना होगा। मैं उस समय एक समस्या पर काम कर रहा हूं जहां किसी ने मानचित्र में कुंजी (स्थान / समय बचाने के लिए) के लिए एक इंट का उपयोग किया। हमें अब सभी लाइनों को एक नई वस्तु में बदलने की आवश्यकता है - इसकी दर्दनाक।
Fortununner

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

4
याद रखें कि प्रोफाइलर परिणाम केवल उस जावा प्लेटफ़ॉर्म के लिए मान्य हैं, जिसके विरुद्ध आप प्रोफ़ाइलर चला रहे हैं। जो आपके ग्राहकों से भिन्न हो सकता है।
मिकेल लोकेके

4
प्रभावी जावा एपीआई की सलाह देता है कि वे एपीआई इंटरऑपरेबिलिटी के साथ मदद करें, और प्रकार की सुरक्षा के साथ अधिक सुरक्षित भी।
जुआनम्फ

164

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

List<String> strings = new ArrayList<String>();

सार डेटा प्रकार और विशिष्ट कार्यान्वयन का यह पृथक्करण वस्तु उन्मुख प्रोग्रामिंग का एक प्रमुख पहलू है।

एक ArrayList सूची सार डेटा प्रकार को उसके अंतर्निहित कार्यान्वयन के रूप में एक सरणी का उपयोग करके लागू करता है। पहुंच की गति लगभग एक सरणी के समान है, जिसमें सूची में तत्वों को जोड़ने और घटाने के अतिरिक्त फायदे हैं (हालांकि यह एक ArrayList के साथ O (n) ऑपरेशन है) और यदि आप अंतर्निहित कार्यान्वयन को बाद में बदलने का निर्णय लेते हैं आप ऐसा कर सकते हैं। उदाहरण के लिए, यदि आपको पता है कि आपको सिंक्रनाइज़ एक्सेस की आवश्यकता है, तो आप अपने सभी कोड को फिर से लिखे बिना वेक्टर के कार्यान्वयन को बदल सकते हैं।

वास्तव में, ArrayList को विशेष रूप से अधिकांश संदर्भों में निम्न-स्तरीय सरणी निर्माण को बदलने के लिए डिज़ाइन किया गया था। यदि जावा को आज डिजाइन किया जा रहा था, तो यह पूरी तरह से संभव है कि सरणियों को ArrayList निर्माण के पक्ष में पूरी तरह से छोड़ दिया गया हो।

चूँकि सरणियाँ मेमोरी के एक सन्निहित भाग में सभी डेटा रखती हैं (सूचियों के विपरीत), हजारों तारों को स्टोर करने के लिए एक सरणी का उपयोग समस्याओं का कारण होगा?

जावा में, सभी संग्रह केवल वस्तुओं को संदर्भित करते हैं, न कि वस्तुओं को। दोनों arrays और ArrayList एक सन्निहित सरणी में कुछ हजार संदर्भों को संग्रहीत करेंगे, इसलिए वे अनिवार्य रूप से समान हैं। आप इस बात पर विचार कर सकते हैं कि कुछ हजार 32-बिट संदर्भों का एक सन्निहित ब्लॉक हमेशा आधुनिक हार्डवेयर पर आसानी से उपलब्ध होगा। यह गारंटी नहीं देता है कि आप पूरी तरह से मेमोरी से बाहर नहीं निकलेंगे, ज़ाहिर है, कि स्मृति आवश्यकता के सन्निहित ब्लॉक को मुश्किल नहीं करना है।


निश्चित रूप से जोड़ने से बैकिंग एरे को पुनः प्राप्त करना शामिल हो सकता है, इसलिए यदि प्रदर्शन महत्वपूर्ण है और एरे के आकार को पहले से जाना जाता है, तो किसी को ArrayList # ensCapacity का उपयोग करने पर विचार करना चाहिए।
जेस्पर

6
क्या आप यहां डायनामिक बाइंडिंग की लागत का भुगतान नहीं करते हैं?
उरई

2
मुझे लगता है कि जोड़ना ArrayList में O (n) नहीं है, एक से अधिक बार जोड़ने पर कुछ अमूर्त प्रभाव होना चाहिए, उदाहरण के लिए क्षमता केवल 1. की वृद्धि की बजाय दोगुनी है
zedoo

@ मुझे लगता है कि वे बीच में जोड़ और घटाना चाहते थे।
माल्कोमोज़ियन

"अगर आज जावा डिजाइन किया जा रहा था, तो यह पूरी तरह से संभव है कि एरेलेस्ट निर्माण के पक्ष में सरणियों को पूरी तरह से छोड़ दिया गया हो।" ... मुझे गंभीरता से संदेह है कि यह सच होगा। यदि यह जेवीएम आज फिर से लिखा जा रहा था, तो आपने जो कहा है वह निश्चित रूप से संभव है। लेकिन हमारे पास जेवीएम के साथ, जावा में एरियर्स एक फाउंडेशनल प्रकार है।
scottb

100

यद्यपि ArrayList का उपयोग करने के प्रस्ताव के जवाब सबसे परिदृश्य में समझ में आते हैं, वास्तव में प्रदर्शन के वास्तविक प्रश्न का उत्तर नहीं दिया गया है।

कुछ चीजें हैं जो आप एक सरणी के साथ कर सकते हैं:

  • इसे बनाओ
  • एक आइटम सेट करें
  • एक आइटम मिलता है
  • क्लोन / इसे कॉपी करें

सामान्य निष्कर्ष

यद्यपि एक ArrayList (मेरी मशीन पर प्रति कॉल 1 और 3 नैनोसेकंड) पर कुछ ऑपरेशन मिलते हैं और सेट होते हैं , लेकिन किसी भी गैर-गहन उपयोग के लिए एक सरणी बनाम ArrayList का उपयोग करने के लिए बहुत कम ओवरहेड है। हालाँकि कुछ बातों का ध्यान रखना चाहिए:

  • एक सूची पर संचालन का आकार बदलना (जब कॉल करना list.add(...)) महंगा हो और किसी को संभव होने पर पर्याप्त स्तर पर प्रारंभिक क्षमता निर्धारित करने का प्रयास करना चाहिए (ध्यान दें कि एक सरणी का उपयोग करते समय एक ही समस्या उत्पन्न होती है)
  • जब आदिमों के साथ काम कर रहे हैं, सरणियां काफी तेज हो सकती हैं क्योंकि वे कई मुक्केबाजी / अनबॉक्सिंग रूपांतरणों से बचने की अनुमति देंगे
  • एक ऐसा एप्लिकेशन जो केवल ArrayList में मान प्राप्त करता है / सेट करता है (बहुत सामान्य नहीं!) एक सरणी पर स्विच करके 25% से अधिक का प्रदर्शन लाभ देख सकता है

विस्तृत परिणाम

यहाँ उन परिणामों के लिए मापी गई है, जो एक मानक x86 डेस्कटॉप मशीन पर JDK 7 के साथ jmh बेंचमार्किंग लाइब्रेरी (नैनोसेकंड में) का उपयोग करके उन तीन ऑपरेशनों के लिए मापा जाता है । ध्यान दें कि परीक्षण में यह सुनिश्चित करने के लिए कि परिणाम समान हैं, ArrayList का आकार कभी बदल नहीं सकता बेंचमार्क कोड यहां उपलब्ध है

ऐरे / एरियरलिस्ट क्रिएशन

मैंने 4 परीक्षण किए, निम्नलिखित कथनों को निष्पादित करना:

  • createArray1: Integer[] array = new Integer[1];
  • createList1: List<Integer> list = new ArrayList<> (1);
  • createArray10000: Integer[] array = new Integer[10000];
  • createList10000: List<Integer> list = new ArrayList<> (10000);

परिणाम (प्रति कॉल में नैनोसेकंड, 95% आत्मविश्वास):

a.p.g.a.ArrayVsList.CreateArray1         [10.933, 11.097]
a.p.g.a.ArrayVsList.CreateList1          [10.799, 11.046]
a.p.g.a.ArrayVsList.CreateArray10000    [394.899, 404.034]
a.p.g.a.ArrayVsList.CreateList10000     [396.706, 401.266]

निष्कर्ष: कोई ध्यान देने योग्य अंतर नहीं

ऑपरेशन करवाएं

मैंने 2 परीक्षण किए, निम्नलिखित कथनों को निष्पादित करना:

  • getList: return list.get(0);
  • getArray: return array[0];

परिणाम (प्रति कॉल में नैनोसेकंड, 95% आत्मविश्वास):

a.p.g.a.ArrayVsList.getArray   [2.958, 2.984]
a.p.g.a.ArrayVsList.getList    [3.841, 3.874]

निष्कर्ष: एक सरणी से प्राप्त करना एक ArrayList से प्राप्त करने की तुलना में लगभग 25% तेज है, हालांकि अंतर केवल एक नैनोसेकंड के आदेश पर है।

संचालन सेट करें

मैंने 2 परीक्षण किए, निम्नलिखित कथनों को निष्पादित करना:

  • सूची सेट करें: list.set(0, value);
  • setArray: array[0] = value;

परिणाम (प्रति कॉल नैनोसेकंड में):

a.p.g.a.ArrayVsList.setArray   [4.201, 4.236]
a.p.g.a.ArrayVsList.setList    [6.783, 6.877]

निष्कर्ष: सरणियों पर सेट ऑपरेशन सूची की तुलना में लगभग 40% तेज हैं , लेकिन, जैसा कि मिलता है, प्रत्येक सेट ऑपरेशन में कुछ नैनोसेकंड लगते हैं - इसलिए 1 सेकंड तक पहुंचने के अंतर के लिए, किसी को सूची / सरणी सैकड़ों में आइटम सेट करने की आवश्यकता होगी लाखों बार!

क्लोन / कॉपी

ArrayList की कॉपी कंस्ट्रक्टर को Arrays.copyOfऐसे प्रदर्शन के लिए प्रत्यायोजित करता है जो सरणी कॉपी के समान है (किसी सरणी को कॉपी करके clone, Arrays.copyOfया System.arrayCopy कोई भौतिक अंतर प्रदर्शन-वार नहीं बनाता है )।


1
अच्छा विश्लेषण। हालाँकि, आपकी टिप्पणी के संबंध में "आदिम लोगों के साथ व्यवहार करते समय, सरणियां काफी तेज हो सकती हैं क्योंकि वे एक को कई मुक्केबाजी / अनबॉक्सिंग रूपांतरणों से बचने की अनुमति देंगे", आप अपना केक खा सकते हैं और इसे भी खा सकते हैं, आदिम-सरणी-समर्थित सूची के साथ कार्यान्वयन; जैसे: github.com/scijava/scijava-common/blob/master/src/main/java/org/… । मैं वास्तव में काफी हैरान हूं कि इस तरह की चीज ने इसे कोर जावा में नहीं बनाया है।
ctrueden

2
@ctrueden ने यह टिप्पणी मानक JDK ArrayList पर लागू की। trove4j एक प्रसिद्ध पुस्तकालय है जो आदिम सूचियों का समर्थन करता है। जावा 8 कई आदिम-विशेष धाराओं के साथ कुछ सुधार लाता है।
assylias

मुझे नहीं पता कि जेएमएच बेंचमार्क कैसे काम करते हैं लेकिन क्या वे जेआईटी संकलन को ध्यान में रखते हैं जो हो सकते हैं? एक जावा एप्लिकेशन का प्रदर्शन समय के साथ भिन्न हो सकता है क्योंकि JVM आपके कोड को संकलित करता है।
हॉफमैन

@ हॉफमैन हां - इसमें एक वार्मअप चरण शामिल है जिसे माप से बाहर रखा गया है।
14

97

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

लेकिन, हमेशा की तरह, जब आपको अनुकूलन करना चाहिए, तो आपको हमेशा इन चरणों का पालन करना चाहिए:

  • तब तक ऑप्टिमाइज़ न करें जब तक आपके पास अपने कोड का अच्छा, साफ और काम करने वाला संस्करण न हो। जेनेरिक प्रकारों को बदलना बहुत अच्छी तरह से इस कदम पर पहले से ही प्रेरित हो सकता है।
  • जब आपके पास एक ऐसा संस्करण है जो अच्छा और साफ है, तो तय करें कि क्या यह काफी तेज है।
  • यदि यह पर्याप्त तेज़ नहीं है, तो इसके प्रदर्शन को मापें । यह कदम दो कारणों से महत्वपूर्ण है। यदि आप नहीं मापते हैं तो आप (1) आपके द्वारा किए गए किसी भी अनुकूलन के प्रभाव को नहीं जानते हैं और (2) जानते हैं कि कहां अनुकूलन करना है।
  • अपने कोड के सबसे गर्म भाग का अनुकूलन करें।
  • फिर से उपाय करें। यह पहले मापने जैसा ही महत्वपूर्ण है। यदि अनुकूलन चीजों में सुधार नहीं करता है, तो इसे वापस लाएं । याद रखें, अनुकूलन के बिना कोड साफ, अच्छा और काम कर रहा था।

24

मुझे लगता है कि मूल पोस्टर C ++ / STL पृष्ठभूमि से आ रहा है जो कुछ भ्रम पैदा कर रहा है। सी ++ std::listमें एक डबल लिंक की गई सूची है।

जावा [java.util.]Listमें एक कार्यान्वयन-मुक्त इंटरफ़ेस (C ++ शब्दों में शुद्ध सार वर्ग) है। Listएक डबल लिंक की गई सूची हो सकती है - java.util.LinkedListप्रदान की गई है। हालांकि, 100 में से 99 बार जब आप एक नया बनाना Listचाहते हैं, तो आप java.util.ArrayListइसके बजाय उपयोग करना चाहते हैं , जो C ++ का लगभग बराबर है std::vector। अन्य मानक कार्यान्वयन भी हैं, जैसे कि उनके द्वारा लौटाए गए java.util.Collections.emptyList()और java.util.Arrays.asList()

एक प्रदर्शन के दृष्टिकोण से, एक इंटरफ़ेस और एक अतिरिक्त ऑब्जेक्ट के माध्यम से जाने के लिए बहुत कम हिट है, हालांकि रनटाइम इनलाइनिंग का मतलब यह शायद ही कोई महत्व है। यह भी याद रखें कि Stringआमतौर पर ऑब्जेक्ट प्लस ऐरे होते हैं। इसलिए प्रत्येक प्रविष्टि के लिए, आपके पास संभवतः दो अन्य ऑब्जेक्ट हैं। C ++ में std::vector<std::string>, हालांकि एक पॉइंटर के बिना मान द्वारा कॉपी करना, जैसे कि वर्ण सरणियाँ स्ट्रिंग के लिए एक ऑब्जेक्ट बनाएंगी (और ये आमतौर पर साझा नहीं की जाएंगी)।

यदि यह विशेष कोड वास्तव में प्रदर्शन के प्रति संवेदनशील है, तो आप सभी स्ट्रिंग्स के सभी पात्रों के लिए एक एकल char[]सरणी (या यहां तक ​​कि byte[]) बना सकते हैं , और फिर ऑफ़सेट का एक सरणी बना सकते हैं। IIRC, यह है कि कैसे javac कार्यान्वित किया जाता है।


1
उत्तर के लिए धन्यवाद। लेकिन नहीं, मैं जावा की इंटरफ़ेस सूची के साथ सी ++ सूची को भ्रमित नहीं कर रहा हूं। मैंने इस तरह से प्रश्न पूछा क्योंकि मैं अर्रेलिस्ट और वेक्टर जैसे सूची कार्यान्वयन के प्रदर्शन की तुलना कच्चे सरणियों से करना चाहता था।
euphoria83

ArrayList और वेक्टर दोनों "सभी डेटा को स्मृति के एक सन्निहित भाग में रखते हैं"।
टॉम हॉल्टिन

13

मैं इस बात से सहमत हूं कि ज्यादातर मामलों में आपको ऐरे के ऊपर ऐरेलिस्ट्स का लचीलापन और लालित्य चुनना चाहिए - और ज्यादातर मामलों में प्रोग्राम के प्रदर्शन पर प्रभाव नगण्य होगा।

हालाँकि, यदि आप थोड़ा संरचनात्मक परिवर्तन (कोई जोड़ नहीं और हटाते हैं), सॉफ़्टवेयर ग्राफिक्स रेंडरिंग या एक कस्टम वर्चुअल मशीन के साथ भारी पुनरावृत्ति कर रहे हैं, तो मेरी अनुक्रमिक पहुंच बेंचमार्किंग परीक्षण बताते हैं कि ArrayLists मेरे से सरणियों से 1.5x धीमे हैं सिस्टम (मेरे एक साल पुराने iMac पर Java 1.6)।

कुछ कोड:

import java.util.*;

public class ArrayVsArrayList {
    static public void main( String[] args ) {

        String[] array = new String[300];
        ArrayList<String> list = new ArrayList<String>(300);

        for (int i=0; i<300; ++i) {
            if (Math.random() > 0.5) {
                array[i] = "abc";
            } else {
                array[i] = "xyz";
            }

            list.add( array[i] );
        }

        int iterations = 100000000;
        long start_ms;
        int sum;

        start_ms = System.currentTimeMillis();
        sum = 0;

        for (int i=0; i<iterations; ++i) {
          for (int j=0; j<300; ++j) sum += array[j].length();
        }

        System.out.println( (System.currentTimeMillis() - start_ms) + " ms (array)" );
        // Prints ~13,500 ms on my system

        start_ms = System.currentTimeMillis();
        sum = 0;

        for (int i=0; i<iterations; ++i) {
          for (int j=0; j<300; ++j) sum += list.get(j).length();
        }

        System.out.println( (System.currentTimeMillis() - start_ms) + " ms (ArrayList)" );
        // Prints ~20,800 ms on my system - about 1.5x slower than direct array access
    }
}

मुझे यह एक दिलचस्प जवाब मिला, लेकिन मुझे आश्चर्य होगा कि अगर यह और भी बदतर है अगर ArrayList स्मृति में एक प्रारंभिक आकार के साथ आरंभीकृत नहीं है। आम तौर पर एक अर्थ में अर्रेइलिस्ट का एक अर्थ में उपयोग करने का लाभ यह है कि आपको पता नहीं चलेगा और आपको चिंता करने की आवश्यकता नहीं है। ArrayLists डिफ़ॉल्ट रूप से प्रारंभिक लंबाई 10 के साथ बनाया जाता है और फिर आकार बदल दिया जाता है। मुझे लगता है कि आकार बदलना महंगा है। मैंने स्पष्ट रूप से बेंचमार्किंग की कोशिश नहीं की है।
ज़ैक पैटरसन

4
इस माइक्रो बेंचमार्क में खामियां हैं (कोई वार्म अप नहीं है, एक अलग तरीके से संचालन नहीं है इसलिए
सरणी सूची

मैं अस्वस्थता से सहमत हूं। इस बेंचमार्क के परिणामों पर भरोसा नहीं किया जाना चाहिए।
स्टीफन सी

@StephenC मैंने एक उचित माइक्रो बेंचमार्क जोड़ा है (जो दिखाता है कि संचालन तुलनात्मक हैं)।
assylias

11

अच्छी तरह से सबसे पहले यह स्पष्ट करने के लायक है कि आप क्लासिक कंप्यूटर विज्ञान डेटा संरचना अर्थ (यानी एक लिंक की गई सूची) में "सूची" का मतलब है या क्या आपका मतलब java.util.List है? यदि आप java.util.List से मतलब रखते हैं, तो यह एक इंटरफ़ेस है। यदि आप किसी सरणी का उपयोग करना चाहते हैं तो केवल ArrayList कार्यान्वयन का उपयोग करें और आपको सरणी जैसा व्यवहार और शब्दार्थ मिलेगा। समस्या सुलझ गयी।

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

सरणी;

  • रैंडम एक्सेस: ओ (1);
  • सम्मिलित करें: O (n);
  • हटाना: O (n)।

लिंक्ड सूची:

  • रैंडम एक्सेस: O (n);
  • सम्मिलित करें: O (1);
  • हटाएं: O (1)।

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

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


मेरा मतलब है java.util.ist इंटरफ़ेस
euphoria83

1
लिंक्डलिस्ट पर रैंडम एक्सेस ओ (एन) मेरे लिए एक बड़ी बात है।
ब्योर्न

11

मैंने ऐरे के साथ ArrayLists की तुलना करने के लिए थोड़ा बेंचमार्क लिखा। मेरे पुराने-ईएसएच लैपटॉप पर, 5000-एलीमेंट एरेलिस्ट के माध्यम से ट्रॉवर्स करने का समय, 1000 बार, बराबर ऐरे कोड की तुलना में 10 मिलीसेकंड धीमा था।

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

nb मैं किया था सूचना है कि का उपयोग कर for String s: stringsListका उपयोग करने के लिए सूची के लिए लूप पुराने तरीके का उपयोग करने की तुलना में लगभग 50% धीमी थी। जाओ आंकड़ा ... यहाँ मैं दो कार्यों का समय है; सरणी और सूची 5000 यादृच्छिक (अलग) तार से भरे हुए थे।

private static void readArray(String[] strings) {
    long totalchars = 0;
    for (int j = 0; j < ITERATIONS; j++) {
        totalchars = 0;
        for (int i = 0; i < strings.length; i++) {
            totalchars += strings[i].length();

        }
    }
}

private static void readArrayList(List<String> stringsList) {
    long totalchars = 0;
    for (int j = 0; j < ITERATIONS; j++) {
        totalchars = 0;
        for (int i = 0; i < stringsList.size(); i++) {
            totalchars += stringsList.get(i).length();
        }
    }
}

@ क्रिस मे: ग्रेट वर्क! दोनों के लिए वास्तविक समय क्या है? क्या आप मुझे बता सकते हैं कि आपके द्वारा उपयोग किए जा रहे तार का आकार क्या है? इसके अलावा, 'स्ट्रिंग s: स्ट्रिंग्सलिस्ट' के उपयोग में अधिक समय लगने के कारण, जावा में उच्चतर अमूर्तता का उपयोग करने में यह मेरा प्राथमिक भय है।
युफोरिया

यह वास्तव में कोई फर्क नहीं पड़ता कि इस mcirobenchmark के लिए तार कितने लंबे हैं। कोई gc नहीं है, और char[]इसे छुआ नहीं गया है (यह C नहीं है)।
टॉम हैटिन

मेरे लिए विशिष्ट समय सरणी संस्करण के लिए ~ 25ms, ArrayList संस्करण के लिए ~ 35ms थे। तार 15-20 चक्के लंबे थे। जैसा कि टॉम कहते हैं, स्ट्रिंग आकार में बहुत अंतर नहीं होता है, ~ 100-चार स्ट्रिंग के साथ समय समान था।
क्रिस मई

3
आपने कैसे नापा? जावा माइक्रो बेंचमार्क में नापी जाने वाली माप आमतौर पर सूचना की तुलना में अधिक गलत सूचना उत्पन्न करती है। उपरोक्त कथन से सावधान रहें।
jmg

6

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


5
सूची भी केवल तार के संदर्भ में संग्रहीत करता है।
पीटर Petertibraný

6

यदि आपके पास हजारों हैं, तो एक त्रि का उपयोग करने पर विचार करें। एक तिकड़ी एक पेड़ जैसी संरचना है जो संग्रहीत स्ट्रिंग के सामान्य उपसर्गों को मिलाती है।

उदाहरण के लिए, यदि तार थे

intern
international
internationalize
internet
internets

तीनों की दुकान होगी:

intern
 -> \0
 international
 -> \0
 -> ize\0
 net
 ->\0
 ->s\0

स्ट्रिंग्स को स्टोरेज के लिए 57 अक्षरों (शून्य टर्मिनेटर, '\ 0' सहित) की आवश्यकता होती है, साथ ही स्ट्रिंग ऑब्जेक्ट का आकार जो भी उन्हें रखता है। (सच में, हमें संभवतः सभी आकारों को 16 के गुणकों तक गोल करना चाहिए, लेकिन ...) इसे 57 + 5 = 62 बाइट्स कहें, मोटे तौर पर।

तीनों को भंडारण के लिए 29 (शून्य टर्मिनेटर, '\ 0' सहित) की आवश्यकता होती है, साथ ही तिकड़ी नोड्स को आकार देते हैं, जो कि एक सरणी के लिए रेफरी और बाल तिकड़ी नोड्स की एक सूची है।

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

अब, अन्य कोड में तीनों का उपयोग करते समय, आपको स्ट्रिंग को परिवर्तित करना होगा, शायद एक स्ट्रिंगर का उपयोग करके मध्यस्थ के रूप में। यदि स्ट्रिंग्स के रूप में स्ट्रिंग्स के रूप में एक बार में कई स्ट्रिंग्स का उपयोग किया जाता है, तो यह नुकसान है।

लेकिन अगर आप उस समय केवल कुछ का उपयोग कर रहे हैं - कहो, एक शब्दकोश में चीजों को देखने के लिए - तिकड़ी आपको बहुत सारे स्थान बचा सकती है। निश्चित रूप से उन्हें हशसेट में संग्रहीत करने की तुलना में कम जगह है।

आप कहते हैं कि आप उन्हें "क्रमबद्ध रूप से" एक्सेस कर रहे हैं - यदि इसका मतलब क्रमिक रूप से वर्णानुक्रम में है, तो त्रिकोणीय भी आपको स्पष्ट रूप से मुफ्त में वर्णानुक्रम देता है, यदि आप इसे गहराई से पहले टाइप करते हैं।


1
एक पुस्तकालय की तरह है या मैं इसे कैसे बनाऊँ?
euphoria83

एक ट्राइकेड स्ट्रिंग्स के मामले में ही उपयोगी होगा, न कि किसी के स्टोरिंग टेक्स्ट को स्ट्रिंग्स के रूप में।
एमएन

5

अपडेट करें:

जैसा कि मार्क ने उल्लेख किया है कि जेवीएम के गर्म होने (कई परीक्षण पास) के बाद कोई महत्वपूर्ण अंतर नहीं है। मैट्रिक्स की नई पंक्ति के साथ फिर से बनाई गई सरणी या यहां तक ​​कि नए पास के साथ चेक किया गया। बड़ी संभावना के साथ, यह सूचकांक के उपयोग के साथ सरल सरणी को संग्रह के पक्ष में उपयोग करने के लिए नहीं है।

अभी भी पहले 1-2 पास सरल सरणी 2-3 गुना तेज है।

मूल पोस्ट:

विषय के लिए बहुत अधिक शब्द बहुत सरल है। बिना किसी प्रश्न के सरणी किसी भी वर्ग कंटेनर की तुलना में कई गुना तेज है । मैं इस सवाल पर अपने प्रदर्शन के महत्वपूर्ण खंड के लिए विकल्प की तलाश में दौड़ता हूं। यहां वास्तविक स्थिति की जांच करने के लिए बनाया गया प्रोटोटाइप कोड है:

import java.util.List;
import java.util.Arrays;

public class IterationTest {

    private static final long MAX_ITERATIONS = 1000000000;

    public static void main(String [] args) {

        Integer [] array = {1, 5, 3, 5};
        List<Integer> list = Arrays.asList(array);

        long start = System.currentTimeMillis();
        int test_sum = 0;
        for (int i = 0; i < MAX_ITERATIONS; ++i) {
//            for (int e : array) {
            for (int e : list) {
                test_sum += e;
            }
        }
        long stop = System.currentTimeMillis();

        long ms = (stop - start);
        System.out.println("Time: " + ms);
    }
}

और यहाँ जवाब है:

सरणी के आधार पर (पंक्ति 16 सक्रिय है):

Time: 7064

सूची के आधार पर (पंक्ति 17 सक्रिय है):

Time: 20950

'तेज' पर कोई और टिप्पणी? यह काफी समझ में आता है। सवाल यह है कि सूची के लचीलेपन की तुलना में लगभग 3 गुना तेज आपके लिए बेहतर है। लेकिन यह एक और सवाल है। वैसे मैंने इसे मैन्युअल रूप से निर्मित के आधार पर भी जांचा ArrayList। लगभग वही परिणाम।


2
3समय तेजी से सच है, लेकिन तुच्छ इसलिए। 14msएक लंबे समय के लिए नहीं है
0x6C38

1
बेंचमार्क जेवीएम को गर्म करने पर विचार नहीं कर रहा है। बार-बार बदलने के लिए मुख्य () से टेस्ट () और कॉल टेस्ट। परीक्षण के 3 या 4 वें रन तक, यह कई बार तेजी से चलता है। उस बिंदु पर, मैं देख रहा हूं कि सरणी सरणी से लगभग 9 गुना तेज है।
माइक

5

चूंकि यहां पहले से ही बहुत सारे अच्छे उत्तर हैं, इसलिए मैं आपको व्यावहारिक दृष्टिकोण की कुछ अन्य जानकारी देना चाहूंगा, जो प्रविष्टि और पुनरावृति प्रदर्शन की तुलना है: जावा में आदिम सरणी बनाम लिंक्ड-सूची।

यह वास्तविक सरल प्रदर्शन जांच है।
तो, परिणाम मशीन के प्रदर्शन पर निर्भर करेगा।

इसके लिए उपयोग किया जाने वाला स्रोत कोड नीचे है:

import java.util.Iterator;
import java.util.LinkedList;

public class Array_vs_LinkedList {

    private final static int MAX_SIZE = 40000000;

    public static void main(String[] args) {

        LinkedList lList = new LinkedList(); 

        /* insertion performance check */

        long startTime = System.currentTimeMillis();

        for (int i=0; i<MAX_SIZE; i++) {
            lList.add(i);
        }

        long stopTime = System.currentTimeMillis();
        long elapsedTime = stopTime - startTime;
        System.out.println("[Insert]LinkedList insert operation with " + MAX_SIZE + " number of integer elapsed time is " + elapsedTime + " millisecond.");

        int[] arr = new int[MAX_SIZE];

        startTime = System.currentTimeMillis();
        for(int i=0; i<MAX_SIZE; i++){
            arr[i] = i; 
        }

        stopTime = System.currentTimeMillis();
        elapsedTime = stopTime - startTime;
        System.out.println("[Insert]Array Insert operation with " + MAX_SIZE + " number of integer elapsed time is " + elapsedTime + " millisecond.");


        /* iteration performance check */

        startTime = System.currentTimeMillis();

        Iterator itr = lList.iterator();

        while(itr.hasNext()) {
            itr.next();
            // System.out.println("Linked list running : " + itr.next());
        }

        stopTime = System.currentTimeMillis();
        elapsedTime = stopTime - startTime;
        System.out.println("[Loop]LinkedList iteration with " + MAX_SIZE + " number of integer elapsed time is " + elapsedTime + " millisecond.");


        startTime = System.currentTimeMillis();

        int t = 0;
        for (int i=0; i < MAX_SIZE; i++) {
            t = arr[i];
            // System.out.println("array running : " + i);
        }

        stopTime = System.currentTimeMillis();
        elapsedTime = stopTime - startTime;
        System.out.println("[Loop]Array iteration with " + MAX_SIZE + " number of integer elapsed time is " + elapsedTime + " millisecond.");
    }
}

प्रदर्शन का परिणाम नीचे है:

यहां छवि विवरण दर्ज करें


4

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


4

याद रखें कि एक ArrayList एक सरणी को एनकैप्सुलेट करता है, इसलिए एक आदिम सरणी का उपयोग करने की तुलना में बहुत कम अंतर है (इस तथ्य को छोड़कर कि जावा में काम करने के लिए एक सूची बहुत आसान है)।

बहुत ही एकमात्र समय यह एक सरणी को पसंद करने के लिए समझ में आता है जब आप आदिम, बाइट, इंट, आदि का भंडारण कर रहे हैं और आपको विशेष अंतरिक्ष-दक्षता की आवश्यकता है जो आप आदिम सरणियों का उपयोग करके प्राप्त करते हैं।


4

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

  1. यदि तारों की संख्या लगभग स्थिर है, तो एक सरणी (या एरियर लाईस्ट) का उपयोग करें। लेकिन अगर संख्या बहुत ज्यादा बदलती है तो आप लिंक्डलिस्ट का बेहतर इस्तेमाल करेंगे।
  2. यदि बीच में तत्वों को जोड़ने या हटाने की आवश्यकता है (या होगी), तो आपको निश्चित रूप से लिंक्डलिस्ट का उपयोग करना होगा।

4

मैं यहां सरणियों की सूची का उपयोग करने के प्रदर्शन प्रभाव के लिए एक बेहतर भावना प्राप्त करने के लिए आया था। मुझे अपने परिदृश्य के लिए यहाँ कोड को अनुकूलित करना था: सरणी / सूची ~ 1000 ints का उपयोग कर ज्यादातर गेटर्स, अर्थ सरणी [j] बनाम list.get (j)

इसके बारे में अवैज्ञानिक होने के लिए 7 का सर्वश्रेष्ठ लेना (पहले कुछ सूची जहां 2.5x धीमी है) मुझे यह मिला:

array Integer[] best 643ms iterator
ArrayList<Integer> best 1014ms iterator

array Integer[] best 635ms getter
ArrayList<Integer> best 891ms getter (strange though)

- तो, ​​सरणी के साथ बहुत मोटे तौर पर 30% तेजी से

अब पोस्ट करने का दूसरा कारण यह है कि कोई भी प्रभाव का उल्लेख नहीं करता है यदि आप नेस्टेड लूप्स के साथ गणित / मैट्रिक्स / सिमुलेशन / ऑप्टिमाइज़ेशन कोड करते हैं ।

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

* EDIT काफी यहाँ चौंक गया, किक्स के लिए मैंने इंटीजर [1000] के बजाय int [1000] घोषित करने की कोशिश की

array int[] best 299ms iterator
array int[] best 296ms getter

Integer [] बनाम int [] का उपयोग करते हुए एक दोहरे प्रदर्शन हिट का प्रतिनिधित्व करता है, सूची के साथ ListArray int [] की तुलना में 3x धीमा है। वास्तव में जावा की सूची कार्यान्वयन मूल सरणियों के समान थे ...

संदर्भ के लिए कोड (कई बार कॉल करें):

    public static void testArray()
    {
        final long MAX_ITERATIONS = 1000000;
        final int MAX_LENGTH = 1000;

        Random r = new Random();

        //Integer[] array = new Integer[MAX_LENGTH];
        int[] array = new int[MAX_LENGTH];

        List<Integer> list = new ArrayList<Integer>()
        {{
            for (int i = 0; i < MAX_LENGTH; ++i)
            {
                int val = r.nextInt();
                add(val);
                array[i] = val;
            }
        }};

        long start = System.currentTimeMillis();
        int test_sum = 0;
        for (int i = 0; i < MAX_ITERATIONS; ++i)
        {
//          for (int e : array)
//          for (int e : list)          
            for (int j = 0; j < MAX_LENGTH; ++j)
            {
                int e = array[j];
//              int e = list.get(j);
                test_sum += e;
            }
        }

        long stop = System.currentTimeMillis();

        long ms = (stop - start);
        System.out.println("Time: " + ms);
    }

3

यदि आप पहले से जानते हैं कि डेटा कितना बड़ा है तो एक सरणी तेजी से होगी।

एक सूची अधिक लचीली है। आप एक ArrayList का उपयोग कर सकते हैं जो एक सरणी द्वारा समर्थित है।


ArrayList में एक EnsCapacity () विधि है जो निर्दिष्ट आकार में बैकिंग सरणी का प्रचार करती है।
जेस्पर

या आप निर्माण के समय आकार निर्दिष्ट कर सकते हैं। यहाँ भी "तेज" का अर्थ है "कुछ माइक्रोसेकंड एक के बजाय दो मेमोरी क्षेत्र आवंटित करने के लिए"
हारून डिगुल्ला

3

यह आप एक निश्चित आकार के साथ रह सकते हैं, सरणियां तेज होंगी और कम मेमोरी की आवश्यकता होगी।

यदि आपको तत्वों को जोड़ने और हटाने के साथ सूची इंटरफ़ेस के लचीलेपन की आवश्यकता है, तो सवाल यह है कि आपको कौन सा कार्यान्वयन चुनना चाहिए। अक्सर ArrayList की सिफारिश की जाती है और किसी भी मामले के लिए उपयोग किया जाता है, लेकिन ArrayList में इसकी प्रदर्शन समस्याएं हैं यदि शुरुआत में या सूची के मध्य में तत्वों को हटाया या डाला जाना चाहिए।

इसलिए आप http://java.dzone.com/articles/gaplist-%E2%80%93-lightning-fast-list पर एक नज़र डालना चाह सकते हैं जो गैपलिस्ट का परिचय देती है। इस नई सूची के कार्यान्वयन से ArrayList और LinkedList दोनों की ताकत मिलती है, जिसके परिणामस्वरूप लगभग सभी ऑपरेशनों के लिए बहुत अच्छा प्रदर्शन होता है।


2

कार्यान्वयन पर निर्भर करता है। यह संभव है कि आदिम प्रकार की एक सरणी ArrayList की तुलना में छोटी और अधिक कुशल होगी। ऐसा इसलिए है क्योंकि सरणी सीधे मानों को मेमोरी के एक सन्निहित ब्लॉक में संग्रहीत करेगी, जबकि सरलतम ArrayList कार्यान्वयन प्रत्येक मूल्य के लिए पॉइंटर्स को संग्रहीत करेगा। 64-बिट प्लेटफॉर्म पर विशेष रूप से, यह एक बड़ा अंतर ला सकता है।

बेशक, जेवीएम कार्यान्वयन के लिए इस स्थिति के लिए एक विशेष मामला होना संभव है, जिस स्थिति में प्रदर्शन समान होगा।


2

सूची जावा 1.5 और उसके बाद का पसंदीदा तरीका है क्योंकि यह जेनरिक का उपयोग कर सकता है। Arrays में जेनेरिक नहीं हो सकता है। इसके अलावा Arrays में एक पूर्व निर्धारित लंबाई होती है, जो गतिशील रूप से नहीं बढ़ सकती है। किसी सरणी को बड़े आकार के साथ प्रारंभ करना एक अच्छा विचार नहीं है। ArrayList जेनेरिक के साथ एक सरणी घोषित करने का तरीका है और यह गतिशील रूप से बढ़ सकता है। लेकिन अगर डिलीट और इंसर्ट को अधिक बार उपयोग किया जाता है, तो लिंक की गई सूची का उपयोग करने के लिए सबसे तेज़ डेटा संरचना है।


2

हर जगह अनुशंसित अनुशंसाएं आप सूची के बजाय उनका उपयोग कर सकते हैं, खासकर अगर आप जानते हैं कि आइटम गिनती और आकार नहीं बदल रहे हैं।

ओरेकल जावा का सबसे अच्छा अभ्यास देखें: http://docs.oracle.com/cd/A97688_16/generic.903/bp/java.htm#1007056

बेशक, अगर आपको संग्रह से वस्तुओं को जोड़ने और हटाने की आवश्यकता है तो कई बार आसान उपयोग सूचियां।


आपके द्वारा जोड़ा गया दस्तावेज़ 10 वर्ष से अधिक पुराना है, अर्थात जावा 1.3 पर लागू होता है। तब से बड़े प्रदर्शन में सुधार किया गया है ...
assylias

@assylias ऊपर उत्तर देखते हैं, उनमें प्रदर्शन परीक्षण शामिल हैं, जो कहते हैं कि सरणियां तेज हैं
निक

3
मुझे पता है कि मैंने उनमें से एक लिखा था। लेकिन मुझे नहीं लगता कि " एरे की सिफारिश हर जगह की जाती है, आप सूचियों के बजाय उनका उपयोग कर सकते हैं " एक अच्छी सलाह है। ज्यादातर स्थितियों में ArrayList डिफ़ॉल्ट विकल्प होना चाहिए जब तक कि आप प्राइमिटिव के साथ काम नहीं कर रहे हैं और आपका कोड प्रदर्शन संवेदनशील है।
अस्वच्छता

2

किसी भी उत्तर में ऐसी जानकारी नहीं थी जो मुझे दिलचस्पी थी - कई बार एक ही सरणी के दोहराव वाले स्कैन। इसके लिए जेएमएच टेस्ट बनाना पड़ा।

परिणाम (Java 1.8.0_66 x32, सादे सरणी को पुनरावृत्त करना ArrayList की तुलना में कम से कम 5 गुना तेज है):

Benchmark                    Mode  Cnt   Score   Error  Units
MyBenchmark.testArrayForGet  avgt   10   8.121 ? 0.233  ms/op
MyBenchmark.testListForGet   avgt   10  37.416 ? 0.094  ms/op
MyBenchmark.testListForEach  avgt   10  75.674 ? 1.897  ms/op

परीक्षा

package my.jmh.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

@State(Scope.Benchmark)
@Fork(1)
@Warmup(iterations = 5, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 10)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class MyBenchmark {

    public final static int ARR_SIZE = 100;
    public final static int ITER_COUNT = 100000;

    String arr[] = new String[ARR_SIZE];
    List<String> list = new ArrayList<>(ARR_SIZE);

    public MyBenchmark() {
        for( int i = 0; i < ARR_SIZE; i++ ) {
            list.add(null);
        }
    }

    @Benchmark
    public void testListForEach() {
        int count = 0;
        for( int i = 0; i < ITER_COUNT; i++ ) {
            for( String str : list ) {
                if( str != null )
                    count++;
            }
        }
        if( count > 0 )
            System.out.print(count);
    }

    @Benchmark
    public void testListForGet() {
        int count = 0;
        for( int i = 0; i < ITER_COUNT; i++ ) {
            for( int j = 0; j < ARR_SIZE; j++ ) {
                if( list.get(j) != null )
                    count++;
            }
        }
        if( count > 0 )
            System.out.print(count);
    }

    @Benchmark
    public void testArrayForGet() {
        int count = 0;
        for( int i = 0; i < ITER_COUNT; i++ ) {
            for( int j = 0; j < ARR_SIZE; j++ ) {
                if( arr[j] != null )
                    count++;
            }
        }
        if( count > 0 )
            System.out.print(count);
    }

}

2

"हजारों" एक बड़ी संख्या नहीं है। कुछ हज़ार पैरा-लंबाई के तार जोड़े के आकार के मेगाबाइट के क्रम पर होते हैं। यदि आप इन सभी को क्रमिक रूप से एक्सेस करना चाहते हैं, तो एक अपरिवर्तनीय एकल लिंक वाली सूची का उपयोग करें


अधिकांश 64-बिट कार्यान्वयन पर 8 बाइट्स।
टॉम हॉकिन - 12

क्या कोई सबूत है कि यह बात java.util.LinkedList से तेज है? जो-इन-मेमोरी ’भी है? इसे अपरिवर्तनीय भी बनाया जा सकता है, जैसे कि इससे कोई अंतर पड़ता है।
लोर्ने

1

बिना उचित बेंचमार्किंग के अनुकूलन के जाल में न पड़ें। जैसा कि दूसरों ने किसी भी धारणा बनाने से पहले एक प्रोफाइलर का उपयोग करने का सुझाव दिया है।

आपके द्वारा बताए गए विभिन्न डेटा संरचनाओं के अलग-अलग उद्देश्य हैं। एक सूची शुरुआत में और अंत में तत्वों को सम्मिलित करने में बहुत कुशल है, लेकिन यादृच्छिक तत्वों तक पहुंचने पर बहुत कुछ भुगतना पड़ता है। एक सरणी में भंडारण नियत है लेकिन तेज यादृच्छिक पहुँच प्रदान करता है। अंत में एक ArrayList इंटरफ़ेस को बढ़ाकर सरणी में सुधार करता है। आम तौर पर उपयोग की जाने वाली डेटा संरचना को यह निर्धारित किया जाना चाहिए कि संग्रहीत डेटा कैसे पहुंच या जोड़ा जाएगा।

मेमोरी खपत के बारे में। तुम कुछ चीजों को मिलाते हुए लगते हो। एक सरणी आपको केवल उस प्रकार के डेटा के लिए स्मृति का एक निरंतर हिस्सा देगा जो आपके पास है। मत भूलो कि जावा में एक निश्चित डेटा प्रकार हैं: बूलियन, चार, इंट, लॉन्ग, फ्लोट और ऑब्जेक्ट (इसमें सभी ऑब्जेक्ट शामिल हैं, यहां तक ​​कि एक सरणी एक ऑब्जेक्ट है)। इसका मतलब है कि यदि आप स्ट्रिंग स्ट्रिंग्स की एक सरणी की घोषणा करते हैं [1000] या MyObject myObjects [1000] तो आपको केवल 1000 मेमोरी बॉक्स मिलते हैं जो ऑब्जेक्ट्स के स्थान (संदर्भ या संकेत) को स्टोर करने के लिए पर्याप्त हैं। आपको ऑब्जेक्ट के आकार को फिट करने के लिए 1000 मेमोरी बॉक्स पर्याप्त नहीं मिलते हैं। यह मत भूलो कि आपकी वस्तुओं को पहले "नया" के साथ बनाया गया है। यह तब होता है जब स्मृति आवंटन किया जाता है और बाद में एक संदर्भ (उनकी स्मृति पता) को सरणी में संग्रहीत किया जाता है। ऑब्जेक्ट केवल उस संदर्भ में सरणी में कॉपी नहीं किया जाता है।


1

मुझे नहीं लगता कि यह स्ट्रिंग्स के लिए वास्तविक अंतर बनाता है। तार की एक सरणी में क्या सन्निहित है, तार के संदर्भ हैं, तार स्वयं स्मृति में यादृच्छिक स्थानों पर संग्रहीत होते हैं।

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



1

यहाँ दिए गए बहुत सारे माइक्रोबैनचर्च में सरणी / एरेलेस्ट रीड जैसी चीजों के लिए कुछ नैनोसेकंड की संख्या पाई गई है। यह काफी उचित है यदि सब कुछ आपके एल 1 कैश में है।

एक उच्च स्तरीय कैश या मुख्य मेमोरी एक्सेस में 10nS-100nS जैसे कुछ के परिमाण समय का आदेश हो सकता है, बनाम L1 कैश के लिए 1nS अधिक। एक ArrayList तक पहुँचने के लिए एक अतिरिक्त मेमोरी इनडायरेक्शन है, और एक वास्तविक एप्लिकेशन में आप इस लागत का भुगतान लगभग कभी भी हर समय से कर सकते हैं, यह इस बात पर निर्भर करता है कि आपका कोड एक्सेस के बीच क्या कर रहा है। और, निश्चित रूप से, यदि आपके पास बहुत से छोटे ArrayLists हैं, तो यह आपके मेमोरी उपयोग में जोड़ सकता है और यह अधिक संभावना बनाता है कि आपके पास कैश कैश होगा।

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

हालांकि, जावा स्ट्रिंग्स, व्यर्थ रूप से बेकार हैं, खासकर यदि आप बहुत से छोटे स्टोर करते हैं (बस उन्हें एक मेमोरी एनालाइज़र के साथ देखें, तो ऐसा लगता है कि> कुछ वर्णों की एक स्ट्रिंग के लिए 60 बाइट्स)। स्ट्रिंग की एक सरणी में स्ट्रिंग ऑब्जेक्ट के लिए एक अप्रत्यक्षता है, और स्ट्रिंग ऑब्जेक्ट से एक चार [] जिसमें स्ट्रिंग ही शामिल है। यदि कुछ भी आपके L1 कैश को उड़ाने वाला है, तो यह हजारों या दसियों हजारों स्ट्रिंग्स के साथ है। इसलिए, यदि आप गंभीर हैं - वास्तव में गंभीर हैं - जितना संभव हो उतना प्रदर्शन को समाप्त करने के बारे में तो आप इसे अलग तरीके से कर सकते हैं। आप कह सकते हैं, दो सरणियों, एक चार [] में सभी तार, एक के बाद एक, और एक int [] शुरू करने के लिए ऑफसेट के साथ पकड़ो। यह कुछ भी करने के लिए PITA होगा, और आपको लगभग निश्चित रूप से इसकी आवश्यकता नहीं है। और अगर तुम करते हो, तुम


0

यह इस पर निर्भर करता है कि आपको इसे कैसे एक्सेस करना है।

भंडारण के बाद, यदि आप मुख्य रूप से कम या कोई इन्सर्ट / डिलीट के साथ सर्च ऑपरेशन करना चाहते हैं, तो ऐरे के लिए जाएं (जैसा कि एरेज़ में ओ (1) में सर्च किया जाता है, जबकि ऐड / डिलीट को तत्वों के री-ऑर्डरिंग की आवश्यकता हो सकती है) ।

भंडारण के बाद, यदि आपका मुख्य उद्देश्य स्ट्रिंग्स को जोड़ना / हटाना है, बहुत कम या कोई खोज ऑपरेशन नहीं है, तो सूची के लिए जाएं।


0

ArrayList आंतरिक रूप से तत्वों को जोड़ने (या स्टोर करने) के लिए सरणी ऑब्जेक्ट का उपयोग करता है। दूसरे शब्दों में, ArrayList को Array data -structure द्वारा समर्थित किया गया है। ArrayList की सरणी resizable (या डायनामिक) है।

ऐरे की तुलना में ऐरे तेजी से होता है क्योंकि एरियरिस्ट आंतरिक रूप उपयोग करता है। अगर हम सीधे एरे में तत्वों को जोड़ सकते हैं और अप्रत्यक्ष रूप से एरेले के माध्यम से एरे में तत्व को जोड़ सकते हैं तो हमेशा प्रत्यक्ष तंत्र अप्रत्यक्ष तंत्र की तुलना में तेज होता है।

ArrayList वर्ग में दो अतिभारित जोड़ () विधियाँ हैं:
1 add(Object) .: सूची के अंत में ऑब्जेक्ट जोड़ता है।
2 add(int index , Object ) .: सूची में निर्दिष्ट स्थान पर निर्दिष्ट ऑब्जेक्ट सम्मिलित करता है।

कैसे ArrayList का आकार गतिशील रूप से बढ़ता है?

public boolean add(E e)        
{       
     ensureCapacity(size+1);
     elementData[size++] = e;         
     return true;
}

उपरोक्त कोड से ध्यान देने योग्य महत्वपूर्ण बात यह है कि हम तत्व जोड़ने से पहले ArrayList की क्षमता की जांच कर रहे हैं। यह सुनिश्चित करता है कि कब्जे वाले तत्वों का वर्तमान आकार क्या है और सरणी का अधिकतम आकार क्या है। यदि भरे हुए तत्वों (ArrayList वर्ग में जोड़े जाने वाले नए तत्व सहित) का आकार सरणी के अधिकतम आकार से अधिक है तो सरणी का आकार बढ़ाएं। लेकिन सरणी के आकार को गतिशील रूप से नहीं बढ़ाया जा सकता है। तो आंतरिक रूप से जो नया होता है वह एरे क्षमता के साथ बनाया जाता है

जावा 6 तक

int newCapacity = (oldCapacity * 3)/2 + 1;

(अपडेट) जावा 7 से

 int newCapacity = oldCapacity + (oldCapacity >> 1);

इसके अलावा, पुराने एरे से डेटा को नए एरे में कॉपी किया जाता है।

ArrayList में ओवरहेड तरीके होने के कारण Array इससे अधिक तेज़ है ArrayList


0

Arrays - यह हमेशा बेहतर होगा जब हमें तेजी से परिणाम प्राप्त करने होंगे

सूचियाँ- प्रविष्टि और विलोपन के परिणाम दिखाते हैं क्योंकि वे O (1) में किए जा सकते हैं और इससे डेटा को जोड़ने, लाने और हटाने के तरीके भी आसानी से उपलब्ध हो जाते हैं। उपयोग करने के लिए बहुत आसान है।

लेकिन हमेशा याद रखें कि जब डेटा संग्रहीत किया जाता है तो सरणी में सूचकांक स्थिति - जब ज्ञात होता है, तो डेटा प्राप्त करना तेज़ होगा।

यह सरणी को क्रमबद्ध करके अच्छी तरह से प्राप्त किया जा सकता है। इसलिए यह डेटा लाने का समय बढ़ाता है (यानी, डेटा को संग्रहीत करना + डेटा सॉर्ट करना + उस स्थिति के लिए खोज करना जहां डेटा पाया जाता है)। इसलिए यह सरणी से डेटा प्राप्त करने के लिए अतिरिक्त विलंबता को बढ़ाता है, भले ही वे डेटा को जल्द लाने में अच्छे हों।

इसलिए इसे ट्राई डेटा संरचना या टर्नरी डेटा संरचना के साथ हल किया जा सकता है। जैसा कि त्रिकोणीय डेटा संरचना के ऊपर चर्चा की गई है, डेटा की खोज में विशेष रूप से ओ (1) परिमाण में खोज की जा सकती है। जब समय मायने रखता है; यदि आपको डेटा को जल्दी से खोजना और पुनः प्राप्त करना है तो आप trie डेटा संरचना के साथ जा सकते हैं।

अगर आप चाहते हैं कि आपकी मेमोरी स्पेस कम हो और आप बेहतर परफॉर्मेंस चाहते हैं तो टर्नरी डेटा स्ट्रक्चर के साथ जाएं। ये दोनों बड़ी संख्या में तार (जैसे शब्दकोष में निहित शब्द) के भंडारण के लिए उपयुक्त हैं।

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