क्यों ArrayDeque LinkedList से बेहतर है


161

मैं यह समझने की कोशिश कर रहा हूं कि Java का ArrayDeque Java के LinkedList से बेहतर क्यों है क्योंकि वे दोनों Deque इंटरफ़ेस को लागू करते हैं।

मैं शायद ही किसी को उनके कोड में ArrayDeque का उपयोग करते हुए देखता हूं। अगर कोई और अधिक प्रकाश डालता है कि कैसे ArrayDeque लागू किया जाता है, तो यह मददगार होगा।

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


5
इस प्रश्न के उत्तर को देखिए जो मैंने कई दिनों पहले किया था: stackoverflow.com/questions/6129805/…
रेनाटो दिनानी

1
फ़ोल्डर में, जहाँ आपने अपना jdk स्थापित किया है, वहाँ एक फ़ाइल है src.zip। यह जावा कक्षाओं के स्रोत कोड के साथ संग्रह है। मैं इन वर्गों की संरचना और आंतरिक अध्ययन के लिए दृढ़ता से सलाह देता हूं कि बेहतर समझ कैसे जावा कक्षाएं काम करती हैं।

जवाबों:


155

लिंक्ड संरचनाएं संभवतः प्रत्येक तत्व पर कैश मिस के साथ पुनरावृति करने के लिए सबसे खराब संरचना हैं। इसके शीर्ष पर वे अधिक स्मृति का उपभोग करते हैं।

यदि आपको दोनों सिरों को जोड़ने / हटाने की आवश्यकता है, तो ArrayDeque एक लिंक्ड सूची की तुलना में काफी बेहतर है। चक्रीय कतार के लिए प्रत्येक तत्व रैंडम एक्सेस O (1) भी है।

लिंक की गई सूची का एकमात्र बेहतर संचालन पुनरावृत्ति के दौरान वर्तमान तत्व को हटा रहा है।


57
ध्यान में रखने के लिए एक और अंतर: लिंक्डलिस्ट शून्य तत्वों का समर्थन करता है, जबकि एरेडेक नहीं करता है।
ल्यूक उशरवुड

15
इसके अलावा एक और छोटा नुकसान (वास्तविक समय के अनुप्रयोगों के लिए) यह है कि एक पुश / ऐड ऑपरेशन पर यह कुछ अधिक लगता है जब एरियरडेक का आंतरिक सरणी भरा हुआ है, क्योंकि इसके आकार को दोगुना करना है और सभी डेटा को कॉपी करना है।
आंद्रेई I

4
@AndreiI, यह कहानी का केवल एक पक्ष है। यहां तक ​​कि अगर आप वास्तविक समय आवेदन और आवश्यक क्षमता के प्रचार के लिए पुनरावृति लागत को बाहर करते हैं, तो जीसी को पूरे लिंक्डलिस्ट को पुनरावृत्त करने की आवश्यकता हो सकती है। मूल रूप से आप जीसी में लागत (जो कि बूट के लिए अधिक हैं) बढ़ रहे हैं।
19'14

3
@DavidT। b / c इसमें फ्रीड नोड की GC लागत शामिल है, असाइन करने पर हेड को कार्ड मार्किंग की भी आवश्यकता हो सकती है (GC के लिए फिर से, यदि लिंक्डलिस्ट पहले से ही जीन में है) ... और यह अतिरिक्त अप्रत्यक्षता (कैश-) के शीर्ष पर है याद आती है) तत्व को वापस करने और त्यागने के लिए।

1
इसके अलावा, जबकि LinkedListलागू नहीं करता है। इसका मतलब है कि इस तरह के तरीके या जबकि नहीं है। यह कभी-कभी महत्वपूर्ण हो सकता है। ListArrayDequeLinkedListindexOfremove(int)ArrayDeque
१६:१६ पर झक्काझोजोव

60

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

यदि यह रुचि का हो सकता है, मेरे पास एक प्रमाण है कि (तत्व जोड़कर) एक तत्व को परिशोधित ArrayListया ArrayDequeनिरंतर समय में चलाता है; का उल्लेख इस


26

ArrayDeque जावा 6 के साथ नया है, यही कारण है कि बहुत सारे कोड (विशेष रूप से परियोजनाएं जो पहले के जावा संस्करणों के साथ संगत होने की कोशिश करते हैं) इसका उपयोग नहीं करते हैं।

यह कुछ मामलों में "बेहतर" है क्योंकि आप सम्मिलित करने के लिए प्रत्येक आइटम के लिए एक नोड आवंटित नहीं कर रहे हैं; इसके बजाय सभी तत्वों को एक विशाल सरणी में संग्रहित किया जाता है, जो भरा हुआ होने पर रिसाइज़ हो जाता है।


17

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

लेकिन, इसका मतलब यह नहीं है, मैं आँख बंद करके ले जाएगा LinkedListकी या ArrayDequeकी ओर। यदि आप जानना चाहते हैं, तो ब्रायन द्वारा किए गए बेंचमार्क पर एक नज़र डालें

परीक्षण सेटअप मानता है:

  • प्रत्येक परीक्षण वस्तु एक 500 वर्ण स्ट्रिंग है। प्रत्येक स्ट्रिंग स्मृति में एक अलग वस्तु है।
  • परीक्षण के दौरान परीक्षण सरणी का आकार विविध होगा।
  • प्रत्येक सरणी आकार / कतार-कार्यान्वयन संयोजन के लिए, 100 परीक्षण चलाए जाते हैं और औसत समय-प्रति-परीक्षण की गणना की जाती है।
  • प्रत्येक परीक्षण में सभी वस्तुओं के साथ प्रत्येक कतार को भरना, फिर उन सभी को निकालना शामिल है।
  • मिलीसेकंड के संदर्भ में समय को मापें।

परीक्षा परिणाम:

  • 10,000 तत्वों से नीचे, लिंक्डलिस्ट और एरियरडेक परीक्षण दोनों उप 1 एमएस स्तर पर औसत थे।
  • जैसे-जैसे डेटा के सेट बड़े होते जाते हैं, ArrayDeque और LinkedList के औसत परीक्षण समय के बीच अंतर बढ़ता जाता है।
  • 9,900,000 तत्वों के परीक्षण आकार में, लिंक्डलिस्ट दृष्टिकोण ने ArrayDeque दृष्टिकोण की तुलना में ~ 165% अधिक समय लिया।

ग्राफ़:

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

ले जाओ:

  • यदि आपकी आवश्यकता 100 या 200 तत्वों को संग्रहीत कर रही है, तो यह क्युबों में से किसी एक का उपयोग करके अधिक अंतर नहीं लाएगा।
  • हालांकि, यदि आप मोबाइल पर विकसित कर रहे हैं, तो आप अधिकतम क्षमता के एक अच्छे अनुमान के साथ ArrayListया उपयोग करना चाह सकते हैं, ArrayDequeजो कि सख्त मेमोरी बाधा के कारण सूची की आवश्यकता हो सकती है।
  • बहुत सारे कोड मौजूद हैं, विशेष रूप LinkedListसे उपयोग करने का निर्णय लेते समय एक बहुत सावधानी से लिखे गए ArrayDequeक्योंकि यह इंटरफ़ेस को लागू नहीं करता Listहै (मुझे लगता है कि यह काफी बड़ा कारण है)। यह हो सकता है कि आपका कोडबेस बड़े पैमाने पर सूची इंटरफ़ेस से बात करता है, शायद सबसे ज्यादा और आप एक में कूदने का फैसला करते हैं ArrayDeque। आंतरिक कार्यान्वयन के लिए इसका उपयोग करना एक अच्छा विचार हो सकता है ...

यह बेंचमार्क जीसी समय को लिंक्ड लिस्ट कचरे के कारण कैसे पकड़ लेगा?
0xbe5077ed

3

ArrayDeque और LinkedList Deque इंटरफ़ेस को लागू कर रहे हैं लेकिन कार्यान्वयन अलग है।

मुख्य अंतर:

  1. ArrayDeque वर्ग के आकार बदलने योग्य सरणी कार्यान्वयन है Deque इंटरफेस और LinkedList कक्षा सूची कार्यान्वयन है

  2. NULL तत्वों को LinkedList में जोड़ा जा सकता है लेकिन ArrayDeque में नहीं

  3. ArrayDeque तुलना में अधिक कुशल है LinkedList दोनों सिरों पर जोड़ और निकाल ऑपरेशन के लिए और LinkedList कार्यान्वयन यात्रा के दौरान वर्तमान तत्व दूर करने के लिए कुशल है

  4. LinkedList कार्यान्वयन की तुलना में अधिक स्मृति की खपत ArrayDeque

तो अगर आपको NULL एलिमेंट्स && का समर्थन नहीं करना है, तो कम मेमोरी और दोनों सिरों पर ऐड / रिमूव तत्वों की दक्षता की तलाश में , ArrayDeque सबसे अच्छा है

अधिक जानकारी के लिए प्रलेखन देखें।


13
"लिंक्ड सूची में, अंतिम तत्व खोजने के लिए ओ (एन) लगेगा।" बिल्कुल सच नहीं है। लिंक्डलिस्ट को एक दोहरी लिंक की गई सूची के रूप में लागू किया गया है ताकि आपको अंतिम तत्व ( header.previous.element) प्राप्त करने के लिए सूची को खोदना न पड़े । "मेमोरी दक्षता" दावे को भी चुनौती दी जा सकती है क्योंकि बैकिंग ऐरे को हमेशा 2 की अगली पावर से बदला जाता है।
Clément MATHIEU

5
"यह अंतिम तत्व खोजने के लिए ओ (एन) ले जाएगा" गलत है। लिंक की गई सूची अंतिम नोड का संदर्भ रखती है और LinkedList.descendingIterator () उस नोड को प्राप्त करती है। तो हमें ओ (1) प्रदर्शन मिलता है। देखें: Coffeeorientedprogramming.wordpress.com/2018/04/23/… (इस प्रकार डाउनवोटिंग)।
सिंह उफिम्त्सेव

1
जब आप Iteratorअंतिम तत्व तक पहुंचने के लिए एक का उपयोग करते हैं, तो ऑपरेशन दोनों वर्गों के लिए ओ (एन) है। जब आप सामान्य Dequeइंटरफ़ेस का उपयोग करते हैं , तो अंतिम तत्व को एक्सेस करना दोनों वर्गों के लिए O (1) है। इसके बावजूद कि आप एक ही समय में O (1) को ArrayDequeO और (N) को देखते हुए किस बिंदु को देखते हैं, LinkedListगलत है।
होल्गर

आपके सभी सुझावों को लिया गया है और सामग्री को सही किया है
रवींद्र बाबू

1

यद्यपि ArrayDeque<E>और LinkedList<E>दोनों ने Deque<E>इंटरफ़ेस को लागू किया है , लेकिन ArrayDeque मूल रूप से ऑब्जेक्ट ऑब्जेक्ट E[]को उसके ऑब्जेक्ट के अंदर रखने के लिए उपयोग करता है, इसलिए यह आम तौर पर सिर और पूंछ तत्वों का पता लगाने के लिए इंडेक्स का उपयोग करता है।

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


-1

हमेशा ऐसा नहीं होता।

उदाहरण के लिए, नीचे के मामले में लेटकोड 103 के अनुसार linkedlistबेहतर प्रदर्शन है ArrayDeque

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> rs=new ArrayList<>();
        if(root==null)
            return rs;
        // 👇 here ,linkedlist works better
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
        boolean left2right=true;
        while(!queue.isEmpty())
        {
            int size=queue.size();
            LinkedList<Integer> t=new LinkedList<>();
            while(size-->0)
            {
                TreeNode tree=queue.remove();
                if(left2right)  
                    t.add(tree.val);
                else
                    t.addFirst(tree.val);
                if(tree.left!=null)
                {
                    queue.add(tree.left);
                }
                if(tree.right!=null)
                {
                    queue.add(tree.right);
                }
            }
            rs.add(t);
            left2right=!left2right;
        }
        return rs;
    }
}

-5

किसी तत्व तक पहुँचने के लिए ArrayDeque की समय जटिलता O (1) है और अंतिम तत्व तक पहुँचने के लिए LinkList है O (N) है। ArrayDeque थ्रेड सुरक्षित नहीं है इसलिए मैन्युअल रूप से सिंक्रोनाइज़ेशन आवश्यक है ताकि आप इसे कई थ्रेड्स के माध्यम से एक्सेस कर सकें और इसलिए वे अधिक तेज़ हैं।


3
यदि आप LinkedListजावा के संदर्भ में बात कर रहे हैं Collection, तो यह दोगुना जुड़ा हुआ है और इसमें सिर और पूंछ तक तेजी से पहुंच है, इसलिए अंतिम तत्व तक पहुंच भी ओ (1) लेती है।
मौरिस

LinkedList में अंतिम तत्व एक्सेस करना O (N) नहीं है। यदि आप descendingIterator () का उपयोग करते हैं, तो यह O (1) में किया जाता है। Coffeeorientedprogramming.wordpress.com/2018/04/23/… (इस प्रकार डाउनवोट ) देखें ।
सिंह उफिम्त्सेव

1
दोनों वर्ग धागा-सुरक्षित नहीं हैं। और वाक्य की शुरुआत के बीच कोई संबंध नहीं है "मैन्युअल रूप से सिंक्रनाइज़ेशन आवश्यक है" और इसका अंत "वे तेज हैं"।
होल्गर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.