2013-03-01 3 views
5

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

उम्मीदें:

  1. ArrayList के बाद से यह करने के लिए "बदलाव" तत्वों, linkedlist के लिए, अपने बस को अद्यतन करने के 2 संदर्भ होते हैं, जब शुरुआत में डालने LinkedList की तुलना में धीमी हो जाएगा।

    वास्तविकता: अधिकांश पुनरावृत्तियों पर समान होने के लिए बाहर आया। कुछ चुनिंदा पुनरावृत्तियों के लिए, यह धीमा था।

  2. शुरुआत में हटाते समय ऐरेलिस्ट लिंक्डलिस्ट से धीमा हो जाएगा, क्योंकि इसे लिंक्डलिस्ट के लिए तत्वों को "स्थानांतरित करना" है, यह केवल एक तत्व को रद्द कर रहा है।

    वास्तविकता: मांग से हटने पर प्रदर्शन समान था।

टेस्ट मामला: 1000000 तत्वों

public static void main(String[] args) { 
    int n = 1000000; 

    List arrayList = new ArrayList(n+10); 
    long milis = System.currentTimeMillis(); 
    for(int i= 0 ;i<n;i++){ 
     arrayList.add(i); 
    } 
    System.out.println("insert arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    List linkedList = new LinkedList(); 
    milis = System.currentTimeMillis(); 
    for(int i= 0 ;i<n;i++){ 
     linkedList.add(i); 
    } 
    System.out.println("insert linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    //System.out.println("Adding at end"); 
    milis = System.currentTimeMillis(); 
    arrayList.add(n-5,n+1); 
    System.out.println("APPEND arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.add(n-5,n+1); 
    System.out.println("APPEND linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    //add at front 
    milis = System.currentTimeMillis(); 
    arrayList.add(0,0); 
    System.out.println("INSERT BEG arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.add(0,0); 
    System.out.println("INSERT BEG linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    //add at middle 
    milis = System.currentTimeMillis(); 
    arrayList.add(n/2,n/2); 
    System.out.println("INSERT MIDDLE arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.add(n/2,n/2); 
    System.out.println("INSERT MIDDLE linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    //get from front, mid, end 
    milis = System.currentTimeMillis(); 
    arrayList.get(0); 
    System.out.println("get front arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.get(0); 
    System.out.println("get front linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    arrayList.get(n/2); 
    System.out.println("get MIDDLE arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.get(n/2); 
    System.out.println("get MIDDLE linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    arrayList.get(n-4); 
    System.out.println("get last arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.get(n-4); 
    System.out.println("get last linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    //delete from front, mid, end. 
    milis = System.currentTimeMillis(); 
    arrayList.remove(0); 
    System.out.println("del front arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.remove(0); 
    System.out.println("del front linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    arrayList.remove(n/2); 
    System.out.println("del mid arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.remove(n/2); 
    System.out.println("del mid linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    arrayList.remove(n-4); 
    System.out.println("del end arraylist takes "+(System.currentTimeMillis()-milis)+" ms"); 

    milis = System.currentTimeMillis(); 
    linkedList.remove(n-4); 
    System.out.println("del end linkedlist takes "+(System.currentTimeMillis()-milis)+" ms"); 

} 

आउटपुट लॉग

insert arraylist takes 141 ms 
insert linkedlist takes 312 ms 
APPEND arraylist takes 0 ms 
APPEND linkedlist takes 0 ms 
INSERT BEG arraylist takes 0 ms 
INSERT BEG linkedlist takes 0 ms 
INSERT MIDDLE arraylist takes 0 ms 
INSERT MIDDLE linkedlist takes 0 ms 
get front arraylist takes 0 ms 
get front linkedlist takes 0 ms 
get MIDDLE arraylist takes 0 ms 
get MIDDLE linkedlist takes 16 ms 
get last arraylist takes 0 ms 
get last linkedlist takes 0 ms 
del front arraylist takes 0 ms 
del front linkedlist takes 0 ms 
del mid arraylist takes 0 ms 
del mid linkedlist takes 15 ms 
del end arraylist takes 0 ms 
del end linkedlist takes 0 ms 

तो कारण क्या है? जेडीके 1.6 इस्तेमाल किया।

संपादित करें: System.nanotime() का उपयोग करने के बाद, मुझे जवाब देने के बाद मुझे जवाब दिए गए। सहमत, यह केवल एक ही परीक्षण है, और औसत होना चाहिए।

insert arraylist takes 137076082 ns 
insert linkdlist takes 318985917 ns 
APPEND arraylist takes 69751 ns 
APPEND linkdlist takes 98126 ns 
**INSERT BEG arraylist takes 2027764 ns 
INSERT BEG linkdlist takes 53522 ns** 
INSERT MIDDLE arraylist takes 1008253 ns 
INSERT MIDDLE linkdlist takes 10395846 ns 
get front arraylist takes 42364 ns 
get front linkdlist takes 77473 ns 
get MIDDLE arraylist takes 39499 ns 
get MIDDLE linkdlist takes 9645996 ns 
get last arraylist takes 46165 ns 
get last linkdlist takes 43446 ns 
**del front arraylist takes 1720329 ns 
del front linkdlist takes 108063 ns** 
del mid arraylist takes 1157398 ns 
del mid linkdlist takes 11845077 ns 
del end arraylist takes 54149 ns 
del end linkdlist takes 49744 ns 
+4

माइक्रो बेंचमार्किंग करते समय हमेशा 'System.nanoTime() ' – Nishant

+1

का उपयोग करें मुझे आश्चर्य है कि आपके मामले में int की ऑटोबॉक्सिंग कितनी समय लेती है, आपके पहले पास पर आप इंटीग्रर्स कैश –

+0

भरकर @ निशांत के साथ सहमत होंगे। अधिकांश परीक्षणों के लिए 0ms सहायक नहीं है। असली समय 50nanoseconds बनाम 300nanoseconds कह सकता है। – mtariq

उत्तर

6

स्पष्टीकरण अपने पहले दो (अजीब) परीक्षण संख्या के लिए है:

ArrayList में सम्मिलित करना आम तौर पर धीमी है क्योंकि यह एक बार आप अपनी सीमाओं को मारा विकसित करने के लिए है। इसे एक नई बड़ी सरणी बनाना होगा, और मूल से डेटा कॉपी करना होगा।

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

इसके अलावा आपके परीक्षण अच्छे नहीं हैं क्योंकि प्रत्येक पुनरावृत्ति में ऑटोबॉक्सिंग (इंट से इंटीजर में रूपांतरण) शामिल होता है - इसमें दोनों को ऐसा करने के लिए अतिरिक्त समय लगेगा और Integers cache की वजह से परिणाम भी खराब हो जाएंगे जो पहले उत्तीर्ण करना।

2

int n = 1000000; बहुत छोटा है। आपको 0 ms मिलता है इसका वास्तव में यह अर्थ नहीं है कि सम्मिलन या हटाना पूरा करने में कोई समय नहीं लगता है। इसका मतलब है कि समय बीत चुका है 1ms से कम है। int n = 1000000; की संख्या बढ़ने का प्रयास करें। आप तब अंतर देख सकते हैं।

संपादित करें: मैंने आपका कोड गलत तरीके से पढ़ा है। मैंने सोचा कि आप सरणी सूची के सामने n तत्व डाल रहे हैं। आपको निश्चित रूप से केवल एक डालने के बजाय कई आइटम डालना चाहिए।

एक और संपादित करें: यदि आप n तत्वों को सम्मिलित करते हैं, तो आपको n का मान बढ़ाने की आवश्यकता नहीं होगी। इसके विपरीत, आप शायद इसे कम करना चाहते हैं क्योंकि ArrayList के सामने डालने में धीमा ऑपरेशन होता है।

+0

@ कार्तिक ओह हाँ।मुझे एहसास हुआ कि टिप्पणी पोस्ट करने से ठीक पहले। फिर भी धन्यवाद। –

0
एक ArrayList के साथ

, मध्यम आपरेशन में डालने सैद्धांतिक बिग ओह के मामले में दो कदम होने जा रहा है:

  • हे (1) स्थिति का पता लगाने और नए मूल्य डालने के लिए
  • हे (एन) शेष मूल्यों को आगे स्थानांतरित करने के लिए।

    • हे (एन) स्थिति
    • पर नोड को खोजने के लिए:
    एक LinkedList साथ

    , अगर प्रासंगिक नोड अभी तक ज्ञात नहीं है (सिर नोड से पाशन), यह भी दो कदम है

    :
  • हे (1) नए मूल्य डालने के लिए

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

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

  • बिग ओह स्थिरांक को अनदेखा करता है जो कुछ डेटासेट पर असर डाल सकता है। उदाहरण के लिए, बबल सॉर्ट ओ (एन * एन) है लेकिन ओ (एन) में प्री-सॉर्टेड सरणी का पता लगा सकता है और लगभग-क्रमबद्ध सरणी के साथ बहुत तेज है।

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

संक्षेप में: सैद्धांतिक धारणाओं से सावधान रहें और हमेशा वास्तविक दुनिया डेटा और संचालन के साथ उपाय करें :)।

संबंधित मुद्दे