Java में ArrayList पर LinkedList का उपयोग कब करें?


3122

मैं हमेशा एक बस का उपयोग करने के लिए किया गया है:

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

मैं इंटरफ़ेस का उपयोग पोर्टेबिलिटी के लिए नाम के रूप में करता हूं, ताकि जब मैं इन जैसे प्रश्न पूछूं तो मैं अपने कोड को पुनः प्राप्त कर सकूं।

कब और इसके विपरीत LinkedListइस्तेमाल किया जाना चाहिए ArrayList?



1
बस LinkedList के लेखक से देखें stackoverflow.com/a/42529652/2032701 और आपको इस मुद्दे का व्यावहारिक बोध मिलेगा।
रुस्लान

जवाबों:


3371

सारांश ArrayList के साथ ArrayDequeमें बेहतर हैं कई और अधिक से अधिक उपयोग-मामले LinkedList। यदि आप निश्चित नहीं हैं - बस के साथ शुरू करते हैं ArrayList


LinkedListऔर ArrayListसूची इंटरफ़ेस के दो अलग-अलग कार्यान्वयन हैं। LinkedListइसे दोहरे लिंक वाली सूची के साथ लागू करता है। ArrayListइसे गतिशील रूप से पुन: आकार देने वाले सरणी के साथ लागू करता है।

मानक लिंक्ड सूची और सरणी संचालन के साथ, विभिन्न तरीकों में अलग-अलग एल्गोरिथम रनटाइम होंगे।

के लिये LinkedList<E>

  • get(int index)है हे (एन) (साथ n / 4 औसत पर कदम), लेकिन हे (1) जब index = 0या index = list.size() - 1(इस मामले में, आप भी उपयोग कर सकते हैं getFirst()और getLast())। के मुख्य लाभों में से एक है LinkedList<E>
  • add(int index, E element)है हे (एन) (साथ n / 4 औसत पर कदम), लेकिन हे (1) जब index = 0या index = list.size() - 1(इस मामले में, आप भी उपयोग कर सकते हैं addFirst()और addLast()/ add())। के मुख्य लाभों में से एक है LinkedList<E>
  • remove(int index)है हे (एन) (साथ n / 4 औसत पर कदम), लेकिन हे (1) जब index = 0या index = list.size() - 1(इस मामले में, आप भी उपयोग कर सकते हैं removeFirst()और removeLast())। के मुख्य लाभों में से एक है LinkedList<E>
  • Iterator.remove()है हे (1)के मुख्य लाभों में से एक है LinkedList<E>
  • ListIterator.add(E element)है हे (1)के मुख्य लाभों में से एक है LinkedList<E>

नोट: कई ऑपरेशनों को औसत पर n / 4 चरणों की आवश्यकता होती है , सबसे अच्छे मामले में निरंतर चरणों की संख्या (जैसे सूचकांक = 0), और n / 2 सबसे खराब स्थिति में (सूची के मध्य)

के लिये ArrayList<E>

  • get(int index)है हे (1)का मुख्य लाभ ArrayList<E>
  • add(E element)है हे (1) परिशोधित, लेकिन हे (एन) बुरी से बुरी हालत के बाद से सरणी का आकार बदला और प्रतिलिपि बनाई जानी चाहिए
  • add(int index, E element)है O (n) ( औसत पर n / 2 चरणों के साथ )
  • remove(int index)है O (n) ( औसत पर n / 2 चरणों के साथ )
  • Iterator.remove()है O (n) ( औसत पर n / 2 चरणों के साथ )
  • ListIterator.add(E element)है O (n) ( औसत पर n / 2 चरणों के साथ )

नोट: आपरेशन के कई की जरूरत n / 2 औसत, पर चरणों लगातार सबसे अच्छा मामले में कदम (सूची के अंत) की संख्या, एन सबसे खराब स्थिति में कदम (सूची के शुरू)

LinkedList<E>पुनरावृत्तियों का उपयोग करके निरंतर-समय सम्मिलन या निष्कासन की अनुमति देता है , लेकिन तत्वों की केवल अनुक्रमिक पहुंच। दूसरे शब्दों में, आप सूची को आगे या पीछे की ओर ले जा सकते हैं, लेकिन सूची में स्थिति खोजने पर सूची के आकार के लिए आनुपातिक समय लगता है। Javadoc का कहना है कि "सूची में अनुक्रमणिका, जो सूची में शुरुआत या अंत से सूची को पार कर लेगी, जो भी करीब हो" , इसलिए वे विधियां औसतन O (n) ( n / 4 चरण) हैं, हालाँकि O (1) के लिए index = 0

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

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

LinkedListजब आप तत्वों को सम्मिलित करने और निकालने के लिए मौजूदा पुनरावृत्तियों का फिर से उपयोग करते हैं, तो एक उत्पन्न होने वाले उपयोग का मुख्य लाभ । ये ऑपरेशन केवल स्थानीय रूप से सूची बदलकर O (1) में किए जा सकते हैं । एक सरणी सूची में, शेष सरणी को स्थानांतरित करने की आवश्यकता है (यानी कॉपी की गई)। दूसरी तरफ, सबसे खराब स्थिति के लिए ओ (एन) ( एन / 2 चरणों) LinkedListमें लिंक का पालन करने वाले साधनों में मांग करते हैं , जबकि एक वांछित स्थिति में गणितीय रूप से गणना की जा सकती है और ओ (1) में एक्सेस किया जा सकता है ।ArrayList

LinkedListसूची के प्रमुख से जब आप जोड़ते या हटाते हैं, तो उत्पन्न होने वाले उपयोग का एक अन्य लाभ , क्योंकि वे संचालन O (1) हैं , जबकि वे O (n) के लिए हैं ArrayList। ध्यान दें कि सिर से जोड़ने और हटाने के लिए ArrayDequeएक अच्छा विकल्प हो सकता है LinkedList, लेकिन यह एक नहीं है List

इसके अलावा, यदि आपके पास बड़ी सूची है, तो ध्यान रखें कि मेमोरी का उपयोग भी अलग है। LinkedListअगले और पिछले तत्वों की ओर संकेत करने के बाद से प्रत्येक का एक तत्व अधिक उपरि है। ArrayListsयह ओवरहेड नहीं है। हालांकि, ArrayListsक्षमता के लिए जितनी स्मृति आवंटित की गई है , ले लो, चाहे तत्व वास्तव में जोड़े गए हों।

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


182
प्रविष्टि लागत का उल्लेख करना भूल गए। एक लिंक्डलिस्ट में, एक बार जब आपके पास सही स्थिति होती है, तो प्रविष्टि O (1) का खर्च होता है, जबकि एक ArrayList में यह O (n) तक जाता है - सम्मिलन बिंदु के पिछले सभी तत्वों को स्थानांतरित करना होगा।
डेविड रॉड्रिग्ज - ड्रिबीज

26
वेक्टर के उपयोग के बारे में: वास्तव में वेक्टर को वापस गिरने की कोई आवश्यकता नहीं है। ऐसा करने का तरीका आपके पसंदीदा सूची कार्यान्वयन और सिंक्रोनाइज़ करने के लिए कॉल करने के लिए इसे एक सिंक्रनाइज़ रैपर देने के लिए है। देखें: java.sun.com/docs/books/tutorial/collections/implementations/…
रयान कॉक्स

69
नहीं, एक लिंक्डलिस्ट के लिए, तब भी O (n) है, भले ही आपको स्थिति पता हो, क्योंकि उस स्थिति में जाने के लिए, अंतर्निहित कार्यान्वयन को उस स्थिति के मान को प्राप्त करने के लिए लिंक की गई सूची के "अगले" पॉइंटर्स को चलना होगा। रैंडम एक्सेस जैसी कोई चीज नहीं है। स्थिति 2 के लिए, पॉइंटर्स चलना सस्ता हो सकता है, लेकिन स्थिति 1 मिलियन के लिए, इतना सस्ता नहीं। बिंदु यह है, यह स्थिति के समानुपाती है, जिसका अर्थ है कि यह ओ (एन) है।
जोनाथन ट्रैन

53
@ केविन यह मायने रखता है कि मेमोरी "एक साथ करीब" है। हार्डवेयर L1 या L2 कैश में तेजी से स्थिर रैम में मेमोरी (डायनेमिक रैम) के सन्निहित ब्लॉक कैश करेगा। सिद्धांत रूप में और व्यावहारिक रूप से अधिकांश समय, स्मृति को यादृच्छिक-पहुंच के रूप में माना जा सकता है। लेकिन वास्तव में, मेमोरी के माध्यम से क्रमिक रूप से पढ़ना यादृच्छिक क्रम की तुलना में थोड़ा तेज होगा। एक प्रदर्शन-महत्वपूर्ण पाश के लिए, यह बात कर सकता है। वे इसे "स्थानिक इलाके" या संदर्भ का इलाका कहते हैं ।
जोनाथन ट्रान

92
वहाँ के रूप में ऐसी कोई बात नहीं है O(n/2)या O(n/4)। बड़े ओ संकेतन आपको बताता है कि कैसे बड़े n के साथ एक ऑपरेशन तराजू होता है । और एक ऑपरेशन स्टेपिंग स्टेप्स को बिल्कुल एक ऑपरेशन स्टेपिंग स्टेप्स की तरह होता है, यही वजह है कि लगातार समन या फैक्टर हटा दिए जाते हैं। और दोनों बस हैं । और वैसे भी अलग-अलग स्थिर कारक होते हैं, इसलिए यह एक की तुलना दूसरे के साथ करने के लिए नहीं करता है, दोनों सिर्फ रैखिक रूप से स्केलिंग कार्यों को दर्शाते हैं। n/2nO(n/2)O(n/4)O(n)LinkedListArrayListO(n/2)O(n/4)
होल्गर

630

इस प्रकार, अब तक किसी को भी आम सहमति के अलावा इन सूचियों में से प्रत्येक की स्मृति पदचिह्न को संबोधित नहीं किया गया है जो कि LinkedList"बहुत अधिक" है, ArrayListइसलिए मैंने कुछ संख्या में क्रंच करने के लिए यह प्रदर्शित करने के लिए कि एन सूची में एन नल संदर्भों के लिए कितनी सूची ली है।

चूँकि संदर्भ या तो 32 या 64 बिट्स होते हैं (तब भी जब नल) अपने रिश्तेदार सिस्टम पर, मैंने 32 और 64 बिट के लिए डेटा के 4 सेट शामिल किए हैं LinkedListsऔर ArrayLists

नोट:ArrayList लाइनों के लिए दिखाए गए आकार छंटनी सूचियों के लिए हैं - व्यवहार में, ए में बैकिंग ऐरे की क्षमता ArrayListआम तौर पर इसके वर्तमान तत्व की तुलना में बड़ी है।

नोट 2: (धन्यवाद BeeOnRope) चूंकि CompressedOops मध्य JDK6 और ऊपर से डिफ़ॉल्ट है, 64-बिट मशीनों के लिए नीचे दिए गए मान मूल रूप से उनके 32-बिट समकक्षों से मेल खाएंगे, जब तक कि निश्चित रूप से आप इसे विशेष रूप से बंद नहीं करते।


लिंक्डलिस्ट और ग्राफ एक्स बाइट्स के ArrayList नंबर का ग्राफ


परिणाम स्पष्ट रूप से दिखाता है कि LinkedListपूरी तरह से बहुत अधिक है ArrayList, विशेष रूप से बहुत उच्च तत्व गणना के साथ। यदि स्मृति एक कारक है, तो स्पष्ट है LinkedLists

मेरे द्वारा उपयोग किए गए सूत्र, मुझे बताएं कि क्या मैंने कुछ गलत किया है और मैं इसे ठीक कर दूंगा। 'b' 32 या 64 बिट सिस्टम के लिए या तो 4 या 8 है, और 'n' तत्वों की संख्या है। मॉड्स का कारण नोट करें क्योंकि जावा में सभी ऑब्जेक्ट्स 8 बाइट्स की एक जगह लेगी चाहे वह सभी का उपयोग किया जाए या नहीं।

सारणी सूची:

ArrayList object header + size integer + modCount integer + array reference + (array oject header + b * n) + MOD(array oject, 8) + MOD(ArrayList object, 8) == 8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8) + MOD(8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8), 8)

लिंक्ड सूची:

LinkedList object header + size integer + modCount integer + reference to header + reference to footer + (node object overhead + reference to previous element + reference to next element + reference to element) * n) + MOD(node object, 8) * n + MOD(LinkedList object, 8) == 8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n + MOD(8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n, 8)


2
यह देखना दिलचस्प है कि लिंक्डलिस्ट को किसी एक तत्व को संग्रहीत करने के लिए ArrayList जितनी स्मृति की आवश्यकता होती है। कितना अचूक! यदि आप अपने उदाहरण को -XX: + UseCompressedOops के साथ चलाते हैं, तो क्या होता है?
jontejj

215
आपके गणित के साथ समस्या यह है कि आपका ग्राफ प्रभाव को बहुत बढ़ा देता है। आप ऑब्जेक्ट्स को मॉडलिंग कर रहे हैं, जिनमें से प्रत्येक में केवल int4, 8 या 8 बाइट्स हैं। लिंक की गई सूची में, ओवरहेड के अनिवार्य रूप से 4 "शब्द" हैं। आपका ग्राफ़ इस प्रकार यह धारणा देता है कि लिंक की गई सूचियाँ, सरणी सूचियों के भंडारण का "पांच गुना" उपयोग करती हैं। ये गलत है। ओवरहेड 16 या 32 बाइट्स प्रति ऑब्जेक्ट है, एक एडिटिव एडजस्टमेंट के रूप में, स्केलिंग फैक्टर नहीं।
हीथ हनीनटुट

6
ArrayList / LinkedList / Node ऑब्जेक्ट्स में से कोई भी केवल एक इंट नहीं है, इसलिए मुझे नहीं मिला कि आप वहां क्या कह रहे हैं। मैंने स्पष्ट करने के लिए 'ऑब्जेक्ट हेडर' के लिए 'ऑब्जेक्ट ओवरहेड' का पुन: निर्धारण किया है - सिस्टम की परवाह किए बिना हर ऑब्जेक्ट के लिए 8 बाइट हैडर है, और हाँ, लिंक्डलिस्ट में सभी नोड ऑब्जेक्ट्स को इनक्लूड करता है, जो कि जहाँ तक हो सके सभी सही ढंग से गिने जाते हैं। कहना। संयोग से, इसे फिर से देखने में, मैंने अपने गणित के साथ लिंक्डलिस्ट में कुछ अन्य समस्याओं का पता लगाया जो वास्तव में इसे विभाजित करता है और एरेएलिस्ट को बदतर बनाता है । मैं इसे अद्यतन रखने के लिए खुश हूं ताकि कृपया स्पष्ट करने में संकोच न करें और फ़रूथर को विस्तृत करें।
न्यूमेरॉन

6
यह ध्यान दिया जाना चाहिए कि CompressedOopsसभी हालिया JDKs में डिफ़ॉल्ट है (7, 8 और कुछ वर्षों के लिए 6 के अपडेट), इसलिए 64-बिट में ArrayListया LinkedListआकारों में कोई फर्क नहीं पड़ेगा , जब तक कि आप स्पष्ट रूप से संकुचित oops बंद नहीं कर देते हैं कुछ कारण।
BeeOnRope

1
@jontejj की डिफ़ॉल्ट क्षमता में वृद्धि 50% है, इसलिए जब आप ArrayListएक प्रारंभिक क्षमता को निर्दिष्ट किए बिना आबाद करते हैं, तो यह अभी भी एक की तुलना में काफी कम मेमोरी का उपयोग करेगा LinkedList
होल्गर

243

ArrayListतुम क्या चाहते हो LinkedListलगभग हमेशा (प्रदर्शन) बग है।

क्यों LinkedListबेकार है:

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

236
माफ़ करना। आपको नीचे चिह्नित किया है। लिंक्डलिस्ट चूसना नहीं करता है। ऐसी परिस्थितियां हैं जहां लिंक्डलिस्ट का उपयोग करने के लिए सही वर्ग है। मैं मानता हूँ कि ऐसी कई स्थितियाँ नहीं हैं जहाँ यह एक सरणी सूची से बेहतर है, लेकिन वे मौजूद हैं। मूर्खतापूर्ण काम करने वाले लोगों को शिक्षित करें!
डेविड टर्नर

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

42
यह यहां सबसे उपयोगी उत्तरों में से एक है। यह शर्म की बात है कि इतने सारे प्रोग्रामर (ए) सार डेटा प्रकार और ठोस कार्यान्वयन के बीच अंतर को समझने में विफल रहते हैं, और (बी) प्रदर्शन को निर्धारित करने में निरंतर कारकों और मेमोरी ओवरहेड के वास्तविक दुनिया के महत्व को समझते हैं।
पोर्कुलस

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

27
@ डेविडविटर: वे मौजूद हैं, लेकिन मुझे लगता है कि टॉम की बात यह थी कि अगर आपको पूछना है, तो आप शायद आर्किमनिस्ट चाहते हैं।
user541686

139

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

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

ArrayList प्रदर्शन के लिए केवल एक बेहतर विकल्प है यदि आप सभी का मतलब प्रदर्शन से थ्रूपुट है और आप विलंबता को अनदेखा कर सकते हैं। अपने काम के अनुभव में मैं सबसे खराब स्थिति की अनदेखी नहीं कर सकता।


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

22
एक बार जब आप 10GB हीप के साथ जावा ऐप प्राप्त करते हैं, तो आप एक पूर्ण GCs के दौरान 25 सेकंड के लिए ऐप लॉक कर सकते हैं, जो टाइमआउट का कारण बनता है । प्रत्येक नोड।
bestsss

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

5
@Andreas: LinkedList हमेशा एक सादे संदर्भ की तुलना में मेमोरी को पांच गुना आवंटित किया जाता है, इसलिए ArrayListअस्थायी रूप से 2.5 गुना की आवश्यकता होती है, फिर भी स्मृति कम नहीं होती है, जबकि स्मृति पुनः प्राप्त नहीं होती है। चूंकि बड़े सरणी आवंटन ईडन स्पेस को बायपास करते हैं, इसलिए उनके पास GC व्यवहार पर कोई प्रभाव नहीं पड़ता है, जब तक कि वास्तव में पर्याप्त मेमोरी नहीं होती है, इस मामले में, LinkedListबहुत पहले उड़ा दिया ...
Holger

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

128
Algorithm           ArrayList   LinkedList
seek front            O(1)         O(1)
seek back             O(1)         O(1)
seek to index         O(1)         O(N)
insert at front       O(N)         O(1)
insert at back        O(1)         O(1)
insert after an item  O(N)         O(1)

एल्गोरिदम: बिग-ओह संकेतन

ArrayLists लिखने-एक बार पढ़ने वाले कई या ऐपेंडर्स के लिए अच्छे हैं, लेकिन सामने या बीच से जोड़ने / हटाने पर बुरा है।


42
आप निरंतर कारकों के बारे में सोचे बिना सीधे बड़े-ओ मानों की तुलना नहीं कर सकते। छोटी सूचियों के लिए (और अधिकांश सूचियाँ छोटी हैं), ArrayList की O (N) LinkedList की O (1) की तुलना में तेज़ है।
पोरकुलस

4
मैं छोटी सूचियों के प्रदर्शन की परवाह नहीं करता, और न ही अपने कंप्यूटर को करता है जब तक कि यह किसी तरह से लूप में उपयोग नहीं किया जाता है।
Maarten Bodewes

45
LinkedList वास्तव में बीच में नहीं डाल सकता है O(1)। सम्मिलन बिंदु खोजने के लिए इसे आधी सूची से गुजरना पड़ता है।
थॉमस अहले

8
लिंक्डलिस्ट: मध्य O (1) में डालें - गलत है! मुझे पता चला कि लिंक्डलिस्ट आकार के 1/10 वें स्थान पर भी सम्मिलन एक तत्व को ArrayList के 1/10 वें स्थान में डालने की तुलना में धीमा है। और इससे भी बदतर: संग्रह का अंत। ArrayList के अंतिम पदों (बहुत अंतिम नहीं) में सम्मिलित करना तेज़ है, फिर LinkedList के अंतिम पदों (बहुत अंतिम नहीं) में
kachanov

14
एक में @kachanov डालने LinkedList है O(1) अगर आप डालने की स्थिति में पुनरावर्तक है , यानी ListIterator.addमाना जाता है कि है O(1)एक के लिए LinkedList
QUIT - Anony-Mousse

107

हाँ, मुझे पता है, यह एक प्राचीन प्रश्न है, लेकिन मैं अपने दो सेंट में फेंक दूंगा:

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

एक सामान्य उपयोग का मामला है जिसमें लिंक्डलिस्ट आउटपरफॉर्म अर्रेलिस्ट: एक कतार से बाहर है। हालाँकि, यदि आपका लक्ष्य प्रदर्शन है, तो लिंक्डलिस्ट के बजाय आपको ArrayBlockingQueue का उपयोग करने पर भी विचार करना चाहिए (यदि आप समय से पहले अपनी कतार के आकार पर ऊपरी सीमा निर्धारित कर सकते हैं, और सभी मेमोरी को फ्रंट में आवंटित करने का जोखिम उठा सकते हैं), या यह CircularArrayList कार्यान्वयन । (हां, यह 2001 से है, इसलिए आपको इसे जनरेट करने की आवश्यकता होगी, लेकिन मुझे हाल ही में जेवीएम में लेख में उद्धृत किए गए तुलनात्मक प्रदर्शन अनुपात मिला है)


39
Java 6 से आप उपयोग कर सकते हैं ArrayDequedocs.oracle.com/javase/6/docs/api/java/util/ArrayDeque.html
थॉमस अहले

1
ArrayDequeLinkedListतब तक धीमी है जब तक कि सभी ऑपरेशन एक ही छोर पर न हों। यह ठीक है जब एक स्टैक के रूप में उपयोग किया जाता है लेकिन यह एक अच्छी कतार नहीं बनाता है।
जेरेमी सूची

2
असत्य - कम से कम Oracle के jdk1.7.0_60 में कार्यान्वयन के लिए और निम्नलिखित परीक्षण में। मैंने एक परीक्षण बनाया जहां मैं 10 मिलियन बार लूप करता हूं और मेरे पास 10 मिलियन रैंडम इंटेगर हैं। लूप के अंदर मैं एक तत्व को प्रदूषित करता हूं और एक निरंतर तत्व प्रदान करता हूं। मेरे कंप्यूटर पर, लिंक्डलिस्ट ArrayDeque की तुलना में 10 गुना धीमा है और कम मेमोरी का उपयोग करता है)। कारण यह है कि ArrayList के विपरीत, ArrayDeque सरणी के प्रमुख के लिए एक संकेतक रखता है ताकि सिर को हटाए जाने पर उसे सभी तत्वों को स्थानांतरित न करना पड़े।
हेन्नो वर्म्यूलेन

6
ArrayDequeStackजब स्टैक के रूप में उपयोग किया जाता है, और LinkedListजब कतार के रूप में उपयोग किया जाता है , तो उससे अधिक तेज़ होने की संभावना है ।
आखिल_मित्तल

3
ध्यान दें कि akhil_mittal की टिप्पणी ArrayDequeप्रलेखन का एक उद्धरण है ।
स्टुअर्ट मार्क्स

65

यह एक दक्षता प्रश्न है। LinkedListतत्वों को जोड़ने और हटाने के लिए तेज़ है, लेकिन एक विशिष्ट तत्व तक पहुंचने के लिए धीमा है। ArrayListएक विशिष्ट तत्व तक पहुंचने के लिए तेज़ है, लेकिन दोनों छोरों को जोड़ने के लिए धीमा हो सकता है, और विशेष रूप से बीच में हटाने के लिए धीमा हो सकता है।

ऐरे बनाम ArrayList बनाम लिंक्डलिस्ट बनाम वेक्टर गहराई में अधिक जाता है, जैसा कि लिंक्ड सूची है


54

सही या गलत: कृपया स्थानीय स्तर पर परीक्षण निष्पादित करें और अपने लिए निर्णय लें!

से संपादित करें / निकालें में तेज LinkedListहै ArrayList

ArrayList, Arrayजिसके द्वारा आकार को दोगुना करने की आवश्यकता होती है, बड़ी मात्रा में अनुप्रयोग से भी बदतर है।

नीचे प्रत्येक ऑपरेशन के लिए यूनिट परीक्षा परिणाम दिया गया है। नैनोस्कॉन्ड्स में परीक्षण दिया गया है।


Operation                       ArrayList                      LinkedList  

AddAll   (Insert)               101,16719                      2623,29291 

Add      (Insert-Sequentially)  152,46840                      966,62216

Add      (insert-randomly)      36527                          29193

remove   (Delete)               20,56,9095                     20,45,4904

contains (Search)               186,15,704                     189,64,981

यहाँ कोड है:

import org.junit.Assert;
import org.junit.Test;

import java.util.*;

public class ArrayListVsLinkedList {
    private static final int MAX = 500000;
    String[] strings = maxArray();

    ////////////// ADD ALL ////////////////////////////////////////
    @Test
    public void arrayListAddAll() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        watch.start();
        arrayList.addAll(stringList);
        watch.totalTime("Array List addAll() = ");//101,16719 Nanoseconds
    }

    @Test
    public void linkedListAddAll() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);

        watch.start();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(stringList);
        watch.totalTime("Linked List addAll() = ");  //2623,29291 Nanoseconds
    }

    //Note: ArrayList is 26 time faster here than LinkedList for addAll()

    ///////////////// INSERT /////////////////////////////////////////////
    @Test
    public void arrayListAdd() {
        Watch watch = new Watch();
        List<String> arrayList = new ArrayList<String>(MAX);

        watch.start();
        for (String string : strings)
            arrayList.add(string);
        watch.totalTime("Array List add() = ");//152,46840 Nanoseconds
    }

    @Test
    public void linkedListAdd() {
        Watch watch = new Watch();

        List<String> linkedList = new LinkedList<String>();
        watch.start();
        for (String string : strings)
            linkedList.add(string);
        watch.totalTime("Linked List add() = ");  //966,62216 Nanoseconds
    }

    //Note: ArrayList is 9 times faster than LinkedList for add sequentially

    /////////////////// INSERT IN BETWEEN ///////////////////////////////////////

    @Test
    public void arrayListInsertOne() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX + MAX / 10);
        arrayList.addAll(stringList);

        String insertString0 = getString(true, MAX / 2 + 10);
        String insertString1 = getString(true, MAX / 2 + 20);
        String insertString2 = getString(true, MAX / 2 + 30);
        String insertString3 = getString(true, MAX / 2 + 40);

        watch.start();

        arrayList.add(insertString0);
        arrayList.add(insertString1);
        arrayList.add(insertString2);
        arrayList.add(insertString3);

        watch.totalTime("Array List add() = ");//36527
    }

    @Test
    public void linkedListInsertOne() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(stringList);

        String insertString0 = getString(true, MAX / 2 + 10);
        String insertString1 = getString(true, MAX / 2 + 20);
        String insertString2 = getString(true, MAX / 2 + 30);
        String insertString3 = getString(true, MAX / 2 + 40);

        watch.start();

        linkedList.add(insertString0);
        linkedList.add(insertString1);
        linkedList.add(insertString2);
        linkedList.add(insertString3);

        watch.totalTime("Linked List add = ");//29193
    }


    //Note: LinkedList is 3000 nanosecond faster than ArrayList for insert randomly.

    ////////////////// DELETE //////////////////////////////////////////////////////
    @Test
    public void arrayListRemove() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        arrayList.addAll(stringList);
        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        arrayList.remove(searchString0);
        arrayList.remove(searchString1);
        watch.totalTime("Array List remove() = ");//20,56,9095 Nanoseconds
    }

    @Test
    public void linkedListRemove() throws Exception {
        Watch watch = new Watch();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(Arrays.asList(strings));

        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        linkedList.remove(searchString0);
        linkedList.remove(searchString1);
        watch.totalTime("Linked List remove = ");//20,45,4904 Nanoseconds
    }

    //Note: LinkedList is 10 millisecond faster than ArrayList while removing item.

    ///////////////////// SEARCH ///////////////////////////////////////////
    @Test
    public void arrayListSearch() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        arrayList.addAll(stringList);
        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        arrayList.contains(searchString0);
        arrayList.contains(searchString1);
        watch.totalTime("Array List addAll() time = ");//186,15,704
    }

    @Test
    public void linkedListSearch() throws Exception {
        Watch watch = new Watch();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(Arrays.asList(strings));

        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        linkedList.contains(searchString0);
        linkedList.contains(searchString1);
        watch.totalTime("Linked List addAll() time = ");//189,64,981
    }

    //Note: Linked List is 500 Milliseconds faster than ArrayList

    class Watch {
        private long startTime;
        private long endTime;

        public void start() {
            startTime = System.nanoTime();
        }

        private void stop() {
            endTime = System.nanoTime();
        }

        public void totalTime(String s) {
            stop();
            System.out.println(s + (endTime - startTime));
        }
    }


    private String[] maxArray() {
        String[] strings = new String[MAX];
        Boolean result = Boolean.TRUE;
        for (int i = 0; i < MAX; i++) {
            strings[i] = getString(result, i);
            result = !result;
        }
        return strings;
    }

    private String getString(Boolean result, int i) {
        return String.valueOf(result) + i + String.valueOf(!result);
    }
}

1
ArrayList को दोगुना नहीं होना चाहिए, सटीक होना चाहिए। कृपया पहले स्रोतों की जांच करें।
डेन्यूबियन नाविक

यह ध्यान दिया जाना चाहिए कि आपका उदाहरण त्रुटिपूर्ण है ... आप बीच की स्ट्रिंग से निकाल रहे हैं: 18 + [2, 12] बाइट्स ("true0false", "true500000false"), औसतन 25 बाइट्स, जो तत्वों के आकार हैं। बीच में। यह ज्ञात है कि जैसा कि तत्व बाइट आकार बढ़ता है, लिंक की गई सूची बेहतर प्रदर्शन करती है, जैसा कि सूची आकार बढ़ता है, एक सन्निहित सरणी (सूची) बेहतर करेगी। सबसे महत्वपूर्ण बात, आप स्ट्रिंग्स पर। असॉल्ट () कर रहे हैं - जो कि एक सस्ता ऑपरेशन नहीं है। यदि आप इसके बजाय पूर्णांक का उपयोग करते हैं, तो मुझे लगता है कि एक अंतर होगा।
सेंटिल

2
"" बड़ी मात्रा में आवेदन में बदतर है ": यह गलतफहमी है। LinkedListअधिक स्मृति ओवरहेड है क्योंकि प्रत्येक तत्व के लिए पाँच क्षेत्रों के साथ एक नोड ऑब्जेक्ट है। कई प्रणालियों पर जो 20 बाइट्स ओवरहेड बनाता है। औसत मेमोरी ओवरहेड प्रति तत्व प्रति ArrayListडेढ़ शब्द है, जो सबसे खराब स्थिति में 6 बाइट्स और 8 बाइट्स बनाता है।
Lii

1
मैंने आपके बेंचमार्क का एक बेहतर संस्करण यहां दिया है, परिणामों के साथ - एरेलिस्ट के लिए ऐपेंड-ऑन-एंड प्रदर्शन आपके लिए कृत्रिम रूप से कम है, क्योंकि addAll बिल्कुल प्रारंभिक आकार का एक भंडारण सरणी दे रहा है, इसलिए पहला इंसर्ट हमेशा ट्रिगर होता है arraycopy। इसके अलावा, इसमें डेटा एकत्र करने से पहले JIT संकलन की अनुमति देने के लिए वार्मअप चक्र शामिल हैं।
BobMcGee

4
जावा 8 के बाद से @BillK का उपयोग कर सकते हैं, removeIf(element -> condition)जहां यह फिट बैठता है, जो ArrayListलूपिंग की तुलना में और इट्रेटर के माध्यम से हटाने के लिए काफी तेज हो सकता है, क्योंकि हर व्यक्तिगत तत्व के लिए शेष पूरे को स्थानांतरित करने की आवश्यकता नहीं है। चाहे यह थ्योरी से बेहतर या बुरा प्रदर्शन LinkedListकरता है, जैसे LinkedListकि सिद्धांत में O (1) विशेष परिदृश्य पर निर्भर करता है , लेकिन सिर्फ एक नोड को हटाने से कई मेमोरी एक्सेस की आवश्यकता होती है, जो ArrayListमहत्वपूर्ण तत्वों को हटाते समय आसानी से आवश्यक संख्या से अधिक हो सकती है। ।
होल्गर

50

ArrayListअनिवार्य रूप से एक सरणी है। LinkedListएक डबल लिंक्ड सूची के रूप में लागू किया गया है।

getबहुत स्पष्ट है। O (1) के लिए ArrayList, क्योंकि ArrayListअनुक्रमणिका का उपयोग करके यादृच्छिक पहुँच की अनुमति दें। O (n) के लिए LinkedList, क्योंकि इसके लिए पहले इंडेक्स ढूंढना होगा। नोट: के विभिन्न संस्करणों देखते हैं addऔर remove

LinkedListजोड़ने और हटाने में तेज है, लेकिन प्राप्त करने में धीमा है। संक्षेप में, LinkedListअगर पसंद किया जाना चाहिए:

  1. तत्व की यादृच्छिक संख्या की कोई बड़ी संख्या नहीं है
  2. बड़ी संख्या में ऐड / रिमूव ऑपरेशन हैं

=== अर्लीलिस्ट ===

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

=== लिंक्डलिस्ट ===

  • जोड़ें (ई ई)

    • सूची के अंत में जोड़ें
    • हे (1)
  • जोड़ें (इंट इंडेक्स, ई तत्व)

    • निर्दिष्ट स्थान पर डालें
    • पहले स्थिति खोजने की जरूरत है
    • पर)
  • हटाना()
    • सूची के पहले तत्व को हटा दें
    • हे (1)
  • निकालें (इंट इंडेक्स)
    • निर्दिष्ट सूचकांक के साथ तत्व निकालें
    • पहले तत्व को खोजने की जरूरत है
    • पर)
  • निकालें (ऑब्जेक्ट ओ)
    • निर्दिष्ट तत्व की पहली घटना को हटा दें
    • पहले तत्व को खोजने की जरूरत है
    • पर)

यहाँ programcreek.com का एक आंकड़ा है ( addऔर removeपहले प्रकार हैं, यानी, सूची के अंत में एक तत्व जोड़ें और सूची में निर्दिष्ट स्थान पर तत्व को हटा दें।):

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


3
"LinkedList ऐड / रिमूव से तेज है"। गलत, stackoverflow.com/a/7507740/638670 से
Nerrve

49

जोशुआ बलोच, लिंक्डलिस्ट के लेखक:

क्या कोई वास्तव में लिंक्डलिस्ट का उपयोग करता है? मैंने इसे लिखा था, और मैं इसका उपयोग कभी नहीं करता।

लिंक: https://twitter.com/joshbloch/status/583813919019573248

मुझे खेद है कि अन्य उत्तरों के रूप में यह जानकारीपूर्ण नहीं है, लेकिन मुझे लगा कि यह सबसे दिलचस्प और आत्म-व्याख्यात्मक होगा।


34

ArrayListबेतरतीब ढंग से सुलभ है, जबकि LinkedListतत्वों का विस्तार करने और हटाने के लिए वास्तव में सस्ता है। ज्यादातर मामलों के लिए, ArrayListठीक है।

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


15
LinkedList तत्वों को जोड़ने के लिए सस्ता नहीं है। एक ArrayList में एक LinkedList में जोड़ने के लिए एक लाख तत्वों को जोड़ना लगभग हमेशा तेज होता है। और वास्तविक-विश्व कोड में अधिकांश सूचियाँ एक लाख तत्व लंबी भी नहीं हैं।
पोरकुलस सिप

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

4
ArrayList में किसी एक आइटम को जोड़ना O (1) है कोई बात नहीं यह 1 मिलियन या 1 बिलियन है। LinkedList में एक आइटम जोड़ना भी O (1) है। "जोड़ना" का अर्थ है अंत में आना।
काचनोव

मेरे द्वारा किए गए कार्यान्वयन को आपने अलग-अलग तरीके से पढ़ा होगा। मेरे अनुभव में, 1 बिलियन तत्व सरणी की प्रतिलिपि बनाने में 1 मिलियन तत्व सरणी की प्रतिलिपि बनाने में अधिक समय लगता है।
डस्टिन

6
@ किचनोव आपको डस्टिन को गलत समझना चाहिए। जब तक आपने 1 बिलियन आइटमों की एक सरणी घोषित नहीं की है, तब आपको अपने सरणी को आकार देने की आवश्यकता होगी, जिस स्थिति में आपको सभी तत्वों को एक नए बड़े सरणी में कॉपी करने की आवश्यकता होगी, इसलिए कभी-कभी आपको O (N) मिलेगा, लेकिन एक लिंक की गई सूची के साथ आप हमेशा रहेंगे get O (1)
स्टेन आर।

28

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


सिद्धांत रूप में, LinkedList के लिए O (1) है add(E element)

एक सूची के बीच में एक तत्व जोड़ना भी बहुत कुशल होना चाहिए।

प्रैक्टिस बहुत अलग है, क्योंकि लिंक्डलिस्ट एक कैश होस्टाइल डेटा संरचना है। प्रदर्शन पीओवी से - ऐसे बहुत कम मामले हैं जहां कैशे के अनुकूल कीLinkedList तुलना में बेहतर प्रदर्शन किया जा सकता है । ArrayList

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

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

बाद की पीढ़ी के हार्डवेयर पर काम करना (बड़ा, अधिक कुशल कैश) - परिणाम और भी निर्णायक हैं:

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

लिंक्डलिस्ट को एक ही काम को पूरा करने में अधिक समय लगता है। source सोर्स कोड

इसके दो मुख्य कारण हैं:

  1. मुख्य रूप से - कि नोड्स LinkedListमेमोरी में बेतरतीब ढंग से बिखरे हुए हैं। RAM ("रैंडम एक्सेस मेमोरी") वास्तव में यादृच्छिक नहीं है और मेमोरी के ब्लॉक को कैश करने के लिए लाया जाना चाहिए। इस ऑपरेशन में समय लगता है, और जब ऐसे भ्रूण अक्सर होते हैं - कैश में मेमोरी पेजों को हर समय बदलने की आवश्यकता होती है -> कैश की याद आती है -> कैश कुशल नहीं है। ArrayListतत्वों को निरंतर मेमोरी पर संग्रहीत किया जाता है - जो कि वास्तव में आधुनिक सीपीयू वास्तुकला के लिए अनुकूलन है।

  2. सेकेंडरी LinkedList बैक / फॉरवर्ड पॉइंटर्स रखने की आवश्यकता होती है, जिसका अर्थ है कि प्रति मेमोरी मेमोरी खपत 3 गुना अधिक है ArrayList

DynamicIntArray , btw, एक कस्टम ArrayList कार्यान्वयन होल्डिंग Int(आदिम प्रकार) है और ऑब्जेक्ट नहीं - इसलिए सभी डेटा वास्तव में आसन्न रूप से संग्रहीत होते हैं - इसलिए और भी अधिक कुशल।

याद रखने के लिए एक महत्वपूर्ण तत्व यह है कि मेमोरी ब्लॉक प्राप्त करने की लागत, एकल मेमोरी सेल तक पहुँचने की लागत से अधिक महत्वपूर्ण है। यही कारण है कि पाठक 1MB अनुक्रमिक मेमोरी मेमोरी के विभिन्न ब्लॉकों से डेटा की इस राशि को पढ़ने की तुलना में x400 गुना अधिक तेज है:

Latency Comparison Numbers (~2012)
----------------------------------
L1 cache reference                           0.5 ns
Branch mispredict                            5   ns
L2 cache reference                           7   ns                      14x L1 cache
Mutex lock/unlock                           25   ns
Main memory reference                      100   ns                      20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy             3,000   ns        3 us
Send 1K bytes over 1 Gbps network       10,000   ns       10 us
Read 4K randomly from SSD*             150,000   ns      150 us          ~1GB/sec SSD
Read 1 MB sequentially from memory     250,000   ns      250 us
Round trip within same datacenter      500,000   ns      500 us
Read 1 MB sequentially from SSD*     1,000,000   ns    1,000 us    1 ms  ~1GB/sec SSD, 4X memory
Disk seek                           10,000,000   ns   10,000 us   10 ms  20x datacenter roundtrip
Read 1 MB sequentially from disk    20,000,000   ns   20,000 us   20 ms  80x memory, 20X SSD
Send packet CA->Netherlands->CA    150,000,000   ns  150,000 us  150 ms

स्रोत: लेटेंसी नंबर हर प्रोग्रामर को जानना चाहिए

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

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

नोट: यह C ++ Std lib का एक मानदंड है, लेकिन मेरा पिछला अनुभव C ++ और जावा परिणाम बहुत समान है। सोर्स कोड

मेमोरी के अनुक्रमिक थोक की नकल करना आधुनिक सीपीयू द्वारा अनुकूलित एक ऑपरेशन है - सिद्धांत बदलना और वास्तव में बनाना, फिर से, ArrayList/ Vectorबहुत अधिक कुशल


क्रेडिट: यहां तैनात सभी बेंचमार्क Kjell Hedström द्वारा बनाए गए हैं । और भी अधिक डेटा उसके ब्लॉग पर पाया जा सकता है


मैं कतार को अद्वितीय या चरम नहीं कहूंगा! एक ArrayList के बजाय एक लिंक्डलिस्ट पर एक 85o कतार को लागू करना बहुत आसान है। यह वास्तव में एक ArrayList पर एक बुरा सपना है क्योंकि आपको अपनी शुरुआत को ट्रैक करना है, रोकना है और अपनी खुद की वसूली करना है, आप एक सरणी का उपयोग कर सकते हैं, लेकिन एक लिंक की गई सूची एक पंद्रह है। मुझे जावा के कार्यान्वयन के बारे में निश्चित नहीं है, लेकिन एक लिंक्डलिस्ट कतार और डीक्यू संचालन दोनों के लिए O (1) कर सकता है (हटाने के लिए टेल एलिमेंट के लिए एक विशेष पॉइंटर की आवश्यकता होती है, जो मुझे लगता है कि जावा में है, लेकिन मैंने डबल-चेक नहीं किया है ।)
बिल K

24

यदि आपका कोड है add(0)और remove(0), एक का उपयोग करें LinkedListऔर यह सुंदर addFirst()और removeFirst()तरीके हैं। अन्यथा, उपयोग करें ArrayList

और निश्चित रूप से, अमरूद के ImmutableList तुम्हारा सबसे अच्छा दोस्त है।


3
छोटी सूचियों के लिए, ArrayList.add (0) अभी भी हमेशा LinkedList.addFirst () की तुलना में तेज़ होने वाला है।
पोरकुलस सिप

1
@Porculus मैं यह तर्क लगातार सुन रहा हूं कि छोटी सूचियों के लिए ArrayList.add (0) तेजी से होगा, यह छोटा कितना छोटा है? 10 तत्व, 10 मिलियन,?
garg10may 12

1
@ garg10may छोटा 10. से कम है
जेसी विल्सन

@Porculus छोटे का अर्थ है ArrayList अंतर्निहित आंतरिक सरणी की अधिकतम क्षमता से कम।
जनक मीणा

21

मैं जानता हूँ कि यह एक पुरानी पोस्ट है, लेकिन मैं ईमानदारी से विश्वास नहीं कर सकता कोई भी उल्लेख किया है कि LinkedListलागू करता Deque। बस Deque(और Queue) में विधियों को देखें ; यदि आप एक उचित तुलना चाहते हैं, के LinkedListखिलाफ चल रहा है ArrayDequeऔर एक सुविधा के लिए सुविधा की तुलना करने की कोशिश करो ।


18

यहाँ दोनों में बिग-ओ अंकन है ArrayListऔर LinkedListऔर यह भी CopyOnWrite-ArrayList:

सारणी सूची

get                 O(1)
add                 O(1)
contains            O(n)
next                O(1)
remove              O(n)
iterator.remove     O(n)

लिंक्ड सूची

get                 O(n)
add                 O(1)
contains            O(n)
next                O(1)
remove              O(1)
iterator.remove     O(1)

CopyOnWrite-ArrayList

get                 O(1)
add                 O(n)
contains            O(n)
next                O(1)
remove              O(n)
iterator.remove     O(n)

इनके आधार पर आपको तय करना है कि क्या चुनना है। :)


9
>>>> ArrayList ऐड -> O (1) <- tru नहीं। कुछ मामलों में ArrayList को एक और तत्व
kachanov

1
लिंक्डलीस्ट हटाने ओ (1) नहीं है, इसे हटाने के लिए तत्व की खोज करने की आवश्यकता होगी, इसलिए सबसे खराब स्थिति हे (एन) और औसत ओ (एन / 2)
garg10may

न तो है LinkedList.add(), हालांकि यहाँ अधिकांश उत्तर ऐसा कहते हैं।
user207421 19

18

मान लें कि लिंक्डलिस्ट और मापदंडों के नीचे ArrayList wrt की तुलना करें:

1. कार्यान्वयन

ArrayList जबकि सूची इंटरफ़ेस का resizable सरणी कार्यान्वयन है

लिंक्डलिस्ट सूची इंटरफ़ेस का डाउली-लिंक्ड सूची कार्यान्वयन है।


2. प्रदर्शन

  • get (int index) या सर्च ऑपरेशन

    ArrayList (int index) ऑपरेशन निरंतर समय में चलता है अर्थात O (1) जबकि

    लिंक्डलिस्ट मिलता है (इंट इंडेक्स) ऑपरेशन रन टाइम O (n) है।

    ArrayList के LinkedList से तेज होने के पीछे का कारण यह है कि ArrayList अपने तत्वों के लिए एक इंडेक्स आधारित प्रणाली का उपयोग करता है क्योंकि यह आंतरिक रूप से एक सरणी डेटा संरचना का उपयोग करता है, दूसरी ओर,

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

  • सम्मिलित करें () या जोड़ें (ऑब्जेक्ट) ऑपरेशन

    AredList की तुलना में LinkedList में सम्मिलन आम तौर पर तेज़ होते हैं। LinkedList में O या (1) ऑपरेशन को जोड़ना या सम्मिलित करना है।

    में रहते हुए ArrayList , अगर सरणी पूर्ण यानी सबसे खराब स्थिति है, वहाँ सरणी का आकार बदलने और नई सरणी, जो ArrayList हे (एन) में जोड़ने के आपरेशन के क्रम में आता है करने के लिए तत्वों को कॉपी करने की एक अतिरिक्त लागत है, अन्यथा यह हे है (1) ।

  • निकालें (इंट) ऑपरेशन

    लिंक्डलिस्ट में ऑपरेशन निकालें आमतौर पर ArrayList यानी O (n) के समान है।

    में LinkedList , वहाँ दो अतिभारित निकालें तरीके हैं। एक को बिना किसी पैरामीटर के हटा दिया जाता है (जो सूची के प्रमुख को हटा देता है और निरंतर समय O (1) में चलता है। LinkedList में अन्य अतिभारित निष्कासन विधि (int) या निष्कासन (ऑब्जेक्ट) है जो ऑब्जेक्ट को हटाता है या int को एक पैरामीटर के रूप में पारित करता है। यह विधि LinkedList को तब तक ट्रेस करती है जब तक कि वह ऑब्जेक्ट न मिल जाए और इसे मूल सूची से अनलिंक न कर दे। इसलिए यह विधि क्रम O (n) है।

    जबकि ArrayList निष्कासन (int) विधि में पुराने सरणी से नए अपडेट किए गए सरणी में तत्वों को कॉपी करना शामिल है, इसलिए इसका रनटाइम O (n) है।


3. रिवर्स इटरेटर

LinkedList को descendingIterator () का उपयोग करते हुए रिवर्स दिशा में पुनरावृत्त किया जा सकता है

ArrayList में कोई अवरोही () नहीं है , इसलिए हमें रिवर्स दिशा में ArrayList पर पुनरावृति करने के लिए अपना कोड लिखना होगा।


4. प्रारंभिक क्षमता

यदि कंस्ट्रक्टर ओवरलोड नहीं है, तो ArrayList प्रारंभिक क्षमता 10 की एक खाली सूची बनाता है, जबकि

लिंक्डलिस्ट बिना किसी प्रारंभिक क्षमता के केवल खाली सूची का निर्माण करता है।


5. मेमोरी ओवरहेड

लिंक्डलिस्ट में मेमोरी ओवरहेड ArrayList की तुलना में अधिक है क्योंकि LinkedList में नोड अगले और पिछले नोड के पते को बनाए रखने की आवश्यकता है। जबकि

में ArrayList प्रत्येक सूचकांक केवल वास्तविक वस्तु (डेटा) आयोजित करता है।


स्रोत


18

मैं आमतौर पर उन विशेष कार्यों की समय जटिलताओं के आधार पर एक का उपयोग करता हूं जो मैं उस विशेष सूची पर करता हूं।

|---------------------|---------------------|--------------------|------------|
|      Operation      |     ArrayList       |     LinkedList     |   Winner   |
|---------------------|---------------------|--------------------|------------|
|     get(index)      |       O(1)          |         O(n)       | ArrayList  |
|                     |                     |  n/4 steps in avg  |            |
|---------------------|---------------------|--------------------|------------|
|      add(E)         |       O(1)          |         O(1)       | LinkedList |
|                     |---------------------|--------------------|            |
|                     | O(n) in worst case  |                    |            |
|---------------------|---------------------|--------------------|------------|
|    add(index, E)    |       O(n)          |         O(n)       | LinkedList |
|                     |     n/2 steps       |      n/4 steps     |            |
|                     |---------------------|--------------------|            |
|                     |                     |  O(1) if index = 0 |            |
|---------------------|---------------------|--------------------|------------|
|  remove(index, E)   |       O(n)          |         O(n)       | LinkedList |
|                     |---------------------|--------------------|            |
|                     |     n/2 steps       |      n/4 steps     |            |
|---------------------|---------------------|--------------------|------------|
|  Iterator.remove()  |       O(n)          |         O(1)       | LinkedList |
|  ListIterator.add() |                     |                    |            |
|---------------------|---------------------|--------------------|------------|


|--------------------------------------|-----------------------------------|
|              ArrayList               |            LinkedList             |
|--------------------------------------|-----------------------------------|
|     Allows fast read access          |   Retrieving element takes O(n)   |
|--------------------------------------|-----------------------------------|
|   Adding an element require shifting | o(1) [but traversing takes time]  |
|       all the later elements         |                                   |
|--------------------------------------|-----------------------------------|
|   To add more elements than capacity |
|    new array need to be allocated    |
|--------------------------------------|

ArrayDeque उन चीज़ों को थोड़ा और संतुलित करता है, जो एसेज़ की ओर कुछ अधिक डालती हैं / आगे / पीछे सभी हटाए जाते हैं O (1) एकमात्र चीज़ जो लिस्टेड है, जो अभी भी जीतती है, ट्रेसिंग (Iterator ऑपरेशंस) को जोड़ / हटा रही है।
बिल K

14

ऊपर अन्य अच्छे तर्क के अलावा, आप नोटिस देना चाहिए ArrayListऔजार RandomAccessइंटरफेस है, जबकि LinkedListऔजार Queue

इसलिए, किसी तरह वे दक्षता और व्यवहार के अंतर के साथ थोड़ी अलग समस्याओं को संबोधित करते हैं (उनके तरीकों की सूची देखें)।


10

यह इस बात पर निर्भर करता है कि आप किन कार्यों को सूची में शामिल करेंगे।

ArrayListअनुक्रमित मान तक पहुँचने के लिए तेज़ है। वस्तुओं को सम्मिलित करते या हटाते समय यह बहुत बुरा होता है।

अधिक जानने के लिए, किसी भी लेख को पढ़ें जो सरणियों और लिंक की गई सूचियों के बीच अंतर के बारे में बात करता है।


2
अधिक जानने के लिए नहीं पढ़ें, बस कोड लिखें। और आपको पता चलेगा कि ArrayList कार्यान्वयन तेजी से है तो प्रविष्टि और विलोपन में LinkedList।
काचनोव

8

एक सरणी सूची अनिवार्य रूप से आइटम आदि जोड़ने के तरीकों के साथ एक सरणी है (और आपको इसके बजाय एक जेनेरिक सूची का उपयोग करना चाहिए)। यह वस्तुओं का एक संग्रह है जिसे एक अनुक्रमणिका के माध्यम से पहुँचा जा सकता है (उदाहरण के लिए [0])। इसका तात्पर्य एक वस्तु से दूसरी वस्तु तक प्रगति से है।

एक लिंक की गई सूची एक आइटम से अगले (आइटम ए -> आइटम बी) तक की प्रगति को निर्दिष्ट करती है। आप एक सरणी सूची के साथ एक ही प्रभाव प्राप्त कर सकते हैं, लेकिन एक लिंक की गई सूची बिल्कुल कहती है कि पिछले आइटम का पालन करने के लिए क्या आइटम माना जाता है।



7

एक लिंक की गई सूची की एक महत्वपूर्ण विशेषता (जिसे मैंने दूसरे उत्तर में नहीं पढ़ा था) दो सूचियों का संयोजन है। एक सरणी के साथ यह O (n) है (कुछ वास्तविकताओं का उपरि भाग) एक लिंक्ड सूची के साथ यह केवल O (1) या O (2) ;-) है

महत्वपूर्ण : जावा के लिए LinkedListयह सच नहीं है! देखें जावा में लिंक की गई सूची के लिए एक तेज़ कॉनैट विधि है?


2
यह कैसा है? यह लिंक्ड सूची डेटा संरचनाओं के साथ सही हो सकता है लेकिन जावा लिंकलिस्ट ऑब्जेक्ट नहीं। आप nextदूसरी सूची में केवल एक सूची से पहली नोड तक इंगित नहीं कर सकते । एकमात्र तरीका यह है कि addAll()जो तत्वों को क्रमिक रूप से जोड़ता है, हालांकि यह add()प्रत्येक तत्व के लिए लूपिंग और कॉलिंग से बेहतर है । O (1) में इसे जल्दी करने के लिए आपको एक कंपोज़िंग क्लास (जैसे org.apache.commons.collections.collection.CompositeCollection) की आवश्यकता होगी, लेकिन तब यह किसी भी प्रकार की सूची / संग्रह के लिए काम करेगा।
केविन ब्रॉक

हाँ सच। मैंने तदनुसार उत्तर संपादित किया। लेकिन लिंक्डलिस्ट के साथ करने के लिए 'कैसे' के लिए यह उत्तर देखें: stackoverflow.com/questions/2494031/…
Karussell

7

ArrayList और LinkedList के अपने पेशेवरों और विपक्ष हैं।

ArrayList LinkedList की तुलना में सन्निहित मेमोरी एड्रेस का उपयोग करता है जो अगले नोड की ओर संकेत करता है। तो जब आप एक तत्व को देखना चाहते हैं, तो AredList में LinkedList के साथ n पुनरावृत्तियों करने की तुलना में तेज़ है।

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

यदि आपके ऐप में लगातार पुनर्प्राप्ति ऑपरेशन होते हैं, तो एक ArrayList का उपयोग करें। यदि आपके पास लगातार प्रविष्टि और विलोपन एक लिंक्डलिस्ट का उपयोग करते हैं।


6

मैंने प्रतिक्रियाओं को पढ़ा है, लेकिन एक ऐसा परिदृश्य है जहां मैं हमेशा एक ArrayList पर एक लिंक्डलिस्ट का उपयोग करता हूं जिसे मैं राय सुनने के लिए साझा करना चाहता हूं:

जब भी मेरे पास एक विधि होती है जो एक DB से प्राप्त डेटा की एक सूची देता है मैं हमेशा एक लिंक्डलिस्ट का उपयोग करता हूं।

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

जहां तक ​​एक ArrayList की बात है, मैं मानता हूं कि कम से कम आपको हमेशा प्रारंभिक क्षमता के साथ कंस्ट्रक्टर का उपयोग करना चाहिए, ताकि जितना संभव हो सके सरणियों के दोहराव को कम किया जा सके।


5

ArrayListऔर LinkedListदोनों लागू होते हैं List interface और उनके तरीके और परिणाम लगभग समान होते हैं। हालांकि उनके बीच कुछ अंतर हैं जो आवश्यकता के आधार पर एक दूसरे पर बेहतर बनाते हैं।

ArrayList Vs LinkedList

1) Search: ArrayListसर्च ऑपरेशन की तुलना में LinkedListसर्च ऑपरेशन काफी तेज है । get(int index)में ArrayListके प्रदर्शन देता है O(1), जबकि LinkedListहै प्रदर्शन O(n)

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

2) Deletion: LinkedListहटाए गए ऑपरेशन, चर प्रदर्शन देते O(1)समय प्रदर्शन ArrayListदेता है: O(n)सबसे खराब स्थिति में (पहले तत्व को हटाते समय) और O(1)सबसे अच्छे मामले में (अंतिम तत्व को हटाते समय)।

निष्कर्ष: ArrayList की तुलना में लिंक्डलिस्ट तत्व विलोपन तेज है।

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

3) Inserts Performance: LinkedListजोड़ने की विधि सबसे खराब स्थिति में O(1)प्रदर्शन ArrayListदेती O(n)है। कारण वही है जिसे हटाने के लिए समझाया गया है।

4) तत्व डेटा और पड़ोसी नोड्स के लिए दो बिंदुओं Memory Overhead: ArrayListको LinkedListबनाए रखते हुए अनुक्रमित और तत्व डेटा बनाए रखता है

इसलिए तुलनात्मक रूप से लिंक्डलिस्ट में मेमोरी की खपत अधिक है।

इन वर्गों के बीच कुछ समानताएं हैं जो इस प्रकार हैं:

  • ArrayList और LinkedList दोनों ही सूची इंटरफ़ेस का कार्यान्वयन कर रहे हैं।
  • वे दोनों तत्वों के सम्मिलन क्रम को बनाए रखते हैं जिसका अर्थ है कि ArrayList और LinkedList तत्वों को प्रदर्शित करते समय परिणाम सेट का वही क्रम होगा जिसमें तत्वों को सूची में डाला गया है।
  • इन दोनों वर्गों को गैर-सिंक्रनाइज़ किया गया है और कलेक्शंस.सिन सिंक्रोनाइज़्डलिस्ट पद्धति का उपयोग करके स्पष्ट रूप से सिंक्रनाइज़ किया जा सकता है।
  • iteratorऔर listIteratorइन कक्षाओं द्वारा लौटाए गए हैं fail-fast(यदि सूची संरचनात्मक रूप से के माध्यम से छोड़कर, किसी भी समय संशोधित किया गया है किसी भी तरह से करने के बाद इटरेटर बनाई गई है iterator’sखुद हटाना होगा या जोड़ने के तरीकों, इटरेटर होगा throwएक ConcurrentModificationException)।

LinkedList का उपयोग कब करें और ArrayList का उपयोग कब करें?

  • डालने और हटाने के ऑपरेशन के ऊपर बताया गया है कि इसकी तुलना (O(1))में अच्छा प्रदर्शन LinkedListहै ArrayList(O(n))

    इसलिए यदि आवेदन में बार-बार जोड़ और विलोपन की आवश्यकता है तो लिंक्डलिस्ट सबसे अच्छा विकल्प है।

  • खोज ( get method) संचालन तेज़ हैं, Arraylist (O(1))लेकिन अंदर नहीं हैंLinkedList (O(n))

    इसलिए यदि संचालन को कम जोड़ने और हटाने और अधिक खोज संचालन की आवश्यकता है, तो ArrayList आपका सबसे अच्छा दांव होगा।


5

ArrayList में ऑपरेशन get (i) लिंक्डलिस्ट की तुलना में तेज़ है, क्योंकि:
ArrayList: सूची इंटरफ़ेस का
रिज़ॉल्यूशन -सरणी कार्यान्वयन LinkedList: सूची और डीके इंटरफ़ेस का डब-लिंक्ड सूची कार्यान्वयन

सूची में अनुक्रमणिका का संचालन सूची को आरंभ या अंत से आगे बढ़ाएगा, जो भी निर्दिष्ट सूचकांक के करीब है।


5

1) डेटा संरचना को समझना

ArrayList और LinkedList के बीच पहला अंतर इस तथ्य के साथ आता है कि ArrayList Array द्वारा समर्थित है जबकि LinkedList LinkedList द्वारा समर्थित है। इससे प्रदर्शन में और अंतर आएगा।

2) लिंक्डलिस्ट लागू करता है Deque

ArrayList और LinkedList के बीच एक और अंतर यह है कि List इंटरफ़ेस के अलावा, LinkedList Deque इंटरफ़ेस को भी लागू करता है, जो ऐड () और पोल () और कई अन्य Deque फ़ंक्शंस के लिए पहले आउट ऑपरेशंस प्रदान करता है। 3) ArrayList में तत्वों को जोड़ना ArrayList में तत्व जोड़ना O (1) ऑपरेशन है अगर यह Array का पुनः आकार ट्रिगर नहीं करता है, तो ऐसी स्थिति में यह O (लॉग (n)) बन जाता है, दूसरी ओर, एक तत्व को जोड़ना लिंक्डलिस्ट O (1) ऑपरेशन है, क्योंकि इसमें किसी भी नेविगेशन की आवश्यकता नहीं है।

4) एक स्थिति से एक तत्व को निकालना

किसी विशेष इंडेक्स से किसी तत्व को निकालने के लिए जैसे कि कॉल हटाएं (इंडेक्स), ArrayList एक कॉपी ऑपरेशन करता है जो इसे O (n) के करीब बनाता है जबकि LinkedList को उस बिंदु तक जाने की आवश्यकता होती है जो इसे O (n / 2) भी बनाता है। , क्योंकि यह निकटता के आधार पर किसी भी दिशा से पार कर सकता है।

5) ArrayList या LinkedList पर Iterating

Iteration, LinkedList और ArrayList दोनों के लिए O (n) ऑपरेशन है जहाँ n एक तत्व का एक नंबर है।

6) एक स्थिति से पुनर्प्राप्त करने वाला तत्व

ArrayList में Get (Index) ऑपरेशन O (1) है, जबकि LinkedList में इसका O (n / 2), क्योंकि इसमें उस प्रविष्टि तक ट्रैवर्स होना आवश्यक है। हालांकि, बिग ओ नोटेशन ओ (एन / 2) में सिर्फ ओ (एन) है क्योंकि हम वहां स्थिरांक को अनदेखा करते हैं।

7) मेमोरी

लिंक्डलिस्ट एक रैपर ऑब्जेक्ट का उपयोग करता है, एंट्री, जो डेटा संग्रहीत करने के लिए एक स्थिर नेस्टेड क्लास है और दो नोड्स अगले और पिछले जबकि ArrayList सिर्फ एरे में डेटा संग्रहीत करता है।

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

अगर एरे काफी बड़ा है तो यह उस बिंदु पर बहुत अधिक मेमोरी ले सकता है और कचरा संग्रह को ट्रिगर कर सकता है, जिससे प्रतिक्रिया समय धीमा हो सकता है।

ArrayList बनाम LinkedList के बीच उपरोक्त सभी अंतरों से, ऐसा लगता है कि ArrayList लगभग सभी मामलों में LinkedList की तुलना में बेहतर विकल्प है, सिवाय इसके कि जब आप लगातार ऐड () ऑपरेशन को हटाने (), या प्राप्त () से जोड़ते हैं।

ArrayList की तुलना में लिंक्ड सूची को संशोधित करना आसान है, खासकर यदि आप तत्वों को शुरू या अंत से जोड़ रहे हैं या हटा रहे हैं क्योंकि लिंक्ड सूची आंतरिक रूप से उन पदों का संदर्भ रखती है और वे ओ (1) समय में सुलभ हैं।

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

मेरी राय में, जावा में व्यावहारिक उद्देश्य के अधिकांश के लिए लिंक्डलिस्ट पर ArrayList का उपयोग करें।


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

3

मैंने यहां जिन परीक्षणों को देखा, उनमें से केवल एक बार परीक्षण किया गया है। लेकिन मैंने जो देखा है वह यह है कि आपको कई बार इन परीक्षणों को चलाने की आवश्यकता है और अंततः उनका समय अभिसिंचित होगा। मूल रूप से जेवीएम को गर्म करने की आवश्यकता है। मेरे विशेष उपयोग के मामले में मुझे एक सूची में आइटम जोड़ने / निकालने की आवश्यकता थी जो लगभग 500 वस्तुओं तक बढ़ती है। मेरे परीक्षणों में LinkedListतेजी से बाहर आया, LinkedListलगभग 50,000 एनएस में और ArrayListलगभग 90,000 एनएस में आने के साथ ... दे या ले। नीचे दिए गए कोड को देखें।

public static void main(String[] args) {
    List<Long> times = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        times.add(doIt());
    }
    System.out.println("avg = " + (times.stream().mapToLong(x -> x).average()));
}

static long doIt() {
    long start = System.nanoTime();
    List<Object> list = new LinkedList<>();
    //uncomment line below to test with ArrayList
    //list = new ArrayList<>();
    for (int i = 0; i < 500; i++) {
        list.add(i);
    }

    Iterator it = list.iterator();
    while (it.hasNext()) {
        it.next();
        it.remove();
    }
    long end = System.nanoTime();
    long diff = end - start;
    //uncomment to see the JVM warmup and get faster for the first few iterations
    //System.out.println(diff)
    return diff;
}

2

दोनों ArrayLists और LinkedLists दोनों के लिए O (n) की रनटाइम दक्षता (और इन्सर्ट) है। हालांकि, रैखिक प्रसंस्करण समय के पीछे का कारण दो अलग-अलग कारणों से आता है:

एक ArrayList में, आप O (1) में तत्व को प्राप्त करते हैं, लेकिन वास्तव में किसी चीज को हटाने या डालने से यह O (n) हो जाता है क्योंकि सभी निम्नलिखित तत्वों को बदलने की आवश्यकता होती है।

एक लिंक्डलिस्ट में, वास्तव में वांछित तत्व को प्राप्त करने के लिए ओ (एन) लेता है, क्योंकि हमें बहुत शुरुआत में शुरू करना है जब तक हम वांछित सूचकांक तक नहीं पहुंचते। वास्तव में हटाना या सम्मिलित करना स्थिर है, क्योंकि हमें केवल हटाने के लिए 1 संदर्भ () और सम्मिलित करने के लिए 2 संदर्भ बदलने हैं ()।

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

बोनस: जबकि एक ArrayList के लिए इन दोनों विधियों O (1) को बनाने का कोई तरीका नहीं है, वास्तव में LinkedLists में ऐसा करने का एक तरीका है। मान लें कि हम अपने रास्ते पर तत्वों को निकालने और सम्मिलित करने की संपूर्ण सूची से गुजरना चाहते हैं। आमतौर पर, आप लिंक्डलिस्ट का उपयोग करते हुए प्रत्येक तत्व के लिए बहुत शुरुआत से शुरू करेंगे, हम एक Iterator के साथ काम कर रहे वर्तमान तत्व को "सेव" भी कर सकते हैं। Iterator की मदद से, हमें एक LinkList में काम करते समय हटाने () और डालने () के लिए O (1) दक्षता प्राप्त होती है। इसे एकमात्र प्रदर्शन लाभ बनाने से मुझे पता है कि जहां एक लिंक्डलिस्ट हमेशा एक ArrayList से बेहतर होता है।


1

ArrayList AbstractList का विस्तार करता है और सूची इंटरफ़ेस को लागू करता है। ArrayList गतिशील सरणी है।
यह कहा जा सकता है कि यह मूल रूप से arrays

की कमियों को दूर करने के लिए बनाया गया था । LinkedList वर्ग AbstractSequentialList और औजार सूची, Deque और कतार इंटरफ़ेस का विस्तार करता है।
प्रदर्शन
arraylist.get()O (1) है, जबकि linkedlist.get()O (n)
arraylist.add()O (1) है और linkedlist.add()0 है (1)
arraylist.contains()O (n) है और linkedlist.contains()O है (n)
arraylist.next()O (1) है और linkedlist.next()O है (1)
arraylist.remove()O (n) है जबकि linkedlist.remove()हे (1) है
में ArrayList
iterator.remove()है हे (एन)
जबकि में linkedlist
iterator.remove()हे है (1)

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