java यादी साफ करण्याची पद्धत. चित्रांमध्ये डेटा संरचना. ॲरेलिस्ट. सूचीच्या "मध्यभागी" जोडत आहे

Viber बाहेर 18.04.2019
Viber बाहेर
12 सप्टेंबर 2011 रोजी संध्याकाळी 6:19 वा

चित्रांमध्ये डेटा संरचना. ArrayList

  • जावा

ग्रीटिंग्ज, हॅब्रा लोक!

Java मध्ये काही डेटा स्ट्रक्चर्स कसे लागू केले जातात याबद्दल अनेक लेख लिहिणे मला वाटले. मला आशा आहे की लेख व्हिज्युअल शिकणाऱ्यांसाठी उपयुक्त ठरतील (चित्रे सर्वकाही आहेत), नवशिक्या जावा व्हिज्युअलायझर्स, तसेच ज्यांना आधीच नवीन ArrayList() कसे लिहायचे ते माहित आहे, परंतु आत काय चालले आहे याची फारशी कल्पना नाही.

आज आपण Arraylists बद्दल बोलू

ArrayList - सूची इंटरफेस लागू करते. म्हणून ओळखले जाते, मध्ये Java ॲरेएक निश्चित लांबी आहे, आणि एकदा ॲरे तयार झाल्यानंतर, ते वाढू किंवा लहान होऊ शकत नाही. प्रोग्रामच्या अंमलबजावणीदरम्यान ॲरेलिस्ट त्याचा आकार बदलू शकते, परंतु ऑब्जेक्ट तयार करताना आकार निर्दिष्ट करणे आवश्यक नाही. ArrayList घटक पूर्णपणे कोणत्याही प्रकारचे असू शकतात, शून्यासह.

ऑब्जेक्ट तयार करणे

ArrayList list = नवीन ArrayList ();
नव्याने तयार केलेल्या सूची ऑब्जेक्टमध्ये गुणधर्म आहेत घटक डेटाआणि आकार.

मूल्य संचयन घटक डेटाॲरेपेक्षा अधिक काही नाही विशिष्ट प्रकार(जेनेरिकमध्ये निर्दिष्ट), आमच्या बाबतीत स्ट्रिंग. जर पॅरामीटर्सशिवाय कन्स्ट्रक्टर कॉल केला असेल, तर डिफॉल्टनुसार ऑब्जेक्ट प्रकारातील 10 घटकांचा ॲरे तयार केला जाईल (अर्थातच टाइप करण्यासाठी कास्टसह).

एक पद्धत आत जोडा(मूल्य)खालील गोष्टी घडतात:

क्षमता सुनिश्चित करा(आकार + 1);
2) शेवटी एक घटक जोडला जातो (मूल्यानुसार आकार) रचना.

ElementData = element;
संपूर्ण पद्धत खात्रीक्षमता(किमान क्षमता)आम्ही याचा विचार करणार नाही, आम्ही फक्त एका जोडप्यावर लक्ष केंद्रित करू मनोरंजक ठिकाणे. ॲरेमध्ये पुरेशी जागा नसल्यास, सूत्र वापरून नवीन क्षमतेची गणना केली जाते (जुनी क्षमता * 3) / 2 + 1. दुसरा मुद्दा घटक कॉपी करणे आहे. वापरून चालते मुळपद्धत System.arraycopy(), जे Java मध्ये लिहिलेले नाही.

// newCapacity - नवीन क्षमता मूल्य elementData = (E)नवीन ऑब्जेक्ट; // oldData - डेटा System.arraycopy (oldData, 0, elementData, 0, आकार) सह वर्तमान ॲरेचे तात्पुरते संचयन;

खाली एक लूप आहे जो एका वेळी 15 घटक जोडतो:
list.add("1");


...

List.add("10");
11 वा घटक जोडताना, चेक दाखवते की ॲरेमध्ये जागा नाही. त्यानुसार, ते तयार केले जाते नवीन ॲरेआणि म्हणतात System.arraycopy().

सूचीच्या "मध्यभागी" जोडत आहे

list.add(5, "100");
विशिष्ट निर्देशांकासह स्थानावर घटक जोडणे तीन टप्प्यांत होते:

1) नवीन घटक घालण्यासाठी ॲरेमध्ये पुरेशी जागा आहे का ते तपासते;

क्षमता सुनिश्चित करा(आकार+1);
2) वापरून नवीन घटकासाठी जागा तयार करा System.arraycopy();

System.arraycopy(elementData, index, elementData, index + 1, size - index);


3) निर्दिष्ट निर्देशांकासह घटकाचे मूल्य अधिलिखित केले आहे.

जसे आपण अंदाज लावू शकता, अशा प्रकरणांमध्ये जेथे एक घटक अनुक्रमणिकेवर घातला जातो आणि नाही मोफत जागा, नंतर कॉल System.arraycopy()दोनदा होईल: प्रथम मध्ये खात्री क्षमता(), पद्धतीमध्येच दुसरा जोडा(निर्देशांक, मूल्य), जे संपूर्ण ऍडिंग ऑपरेशनच्या गतीवर स्पष्टपणे परिणाम करेल.

ज्या प्रकरणांमध्ये मूळ सूचीमध्ये दुसरा संग्रह जोडणे आवश्यक आहे आणि अगदी "मध्यम" मध्ये, पद्धत वापरणे फायदेशीर आहे सर्व जोडा(निर्देशांक, संकलन). आणि जरी ही पद्धतबहुधा कारणीभूत ठरेल System.arraycopy()तीन वेळा, शेवटी ते घटक-बाय-घटक जोडण्यापेक्षा खूप वेगवान असेल.

आयटम काढत आहे

तुम्ही घटक दोन प्रकारे हटवू शकता:
- निर्देशांकानुसार काढा(निर्देशांक)
- मूल्यानुसार काढा(मूल्य)

निर्देशांकानुसार घटक हटवणे अगदी सोपे आहे

List.remove(5);
प्रथम, किती घटक कॉपी करणे आवश्यक आहे ते ठरवा

Int numMoved = आकार - निर्देशांक - 1;
नंतर घटक वापरून कॉपी करा System.arraycopy()

System.arraycopy(elementData, index + 1, elementData, index, numMoved);
ॲरेचा आकार कमी करा आणि शेवटच्या घटकाबद्दल विसरून जा

ElementData[---size] = शून्य; // gc ला त्याचे काम करू द्या

मूल्यानुसार काढून टाकताना, जुळणी सापडेपर्यंत लूप सूचीतील सर्व घटकांमधून जातो. सापडलेला फक्त पहिला घटक हटवला जाईल.

परिशिष्ट १:योग्य नोंद केल्याप्रमाणे

मागील लेक्चरमध्ये, आम्ही व्हेरिएबल-लांबीच्या ॲरेच्या अंमलबजावणीपैकी एकावर स्पर्श केला - LinkedList सूची वापरून अंमलबजावणी . यावेळी आम्ही पर्यायी आवृत्ती पाहू: ArrayList .

ArrayList वापरण्यासाठी Java मध्ये तुम्हाला ArrayList क्लास इंपोर्ट करणे आवश्यक आहे:

Java.util.ArrayList आयात करा;

ArrayList एक वर्ग आहे ज्याच्या खोलीत कुठेतरी घटकांचे संदर्भ आहेत प्रकारआणि ArrayList चा आकार असलेले फील्ड . ArrayList सह काम करण्यासाठी ऑपरेशन्स LinkedList सह कार्य करण्यासाठी ऑपरेशन्स प्रमाणेच . ArrayList वर्ग लक्षात ठेवा प्रोग्रामरला ॲरेमध्ये थेट प्रवेश करण्याची परवानगी देत ​​नाही. शिवाय, प्रोग्रामर केवळ त्याने स्वतः तयार केलेल्या ॲरेचे घटक हाताळू शकतो.

उदाहरण.

ArrayList list = नवीन ArrayList ();

या ओळीने आपण ArrayList क्लासचा एक ऑब्जेक्ट तयार केला आहे . याने दहा पूर्णांक संदर्भांचा ॲरे तयार केला (10 ही ॲरेलिस्टमधील ॲरेची लांबी आहे डीफॉल्ट). तथापि, या ॲरेचे कोणतेही फील्ड आमच्यासाठी उपलब्ध नाहीत, आणि "list.isEmpty();" खरे परत येईल. आमच्या सूचीमध्ये अद्याप कोणतेही घटक नाहीत. चित्रात ते असे काहीतरी दिसेल:

अर्ज केल्यानंतर "list.add(5);" आम्हाला खालील चित्र मिळते:

जर आपण एखादे घटक सलग दहा वेळा जोडले आणि ते अकराव्या वेळी करायचे असेल तर आपल्याला समस्या येईल. समस्या अशी आहे की आमची सूचीमधील ॲरे संपली आहे आणि आमच्याकडे डेटा लिहिण्यासाठी कोठेही नाही. म्हणून आपल्याला ॲरे विस्तृत करणे आवश्यक आहे. हे आपोआप घडते. हे करण्यासाठी, अधिक लांबीचा एक नवीन ॲरे तयार केला जातो आणि मागील ॲरेमधील मूल्ये त्यात कॉपी केली जातात. हे खूप महाग ऑपरेशन आहे आणि अंदाजे O(N) पुनरावृत्ती घेते. ArrayList वर्गात नवीन ॲरेची लांबी जुन्या ॲरेच्या लांबीच्या दीड पटीने ओलांडते. एकूण, जर तुम्ही सलग 11 वेळा "list.add(5);" ऑपरेशन केले, तर तुम्हाला खालील चित्रासारखे काहीतरी मिळेल:

हे देखील लक्षात ठेवा की "list.remove(index);" ऑपरेशन करणे. सूचीमधील ॲरेची वास्तविक लांबी कमी करणार नाही.

ArrayList साठी सरासरी ऑपरेशन वेळा सारणी .

आता ArrayList वरील ऑपरेशन्सच्या एसिम्प्टोटिक एक्झिक्यूशन वेळेचा विचार करूया :

लक्षात घ्या की add(value) आणि add(index, value) रन वेळा अनुक्रमे O(1) आणि O(आकार - इंडेक्स) आहेत, जरी या ऑपरेशन्स सर्वात वाईट परिस्थितीत O(आकार) चालवतात. ॲड(व्हॅल्यू) ऑपरेशनसाठी सरासरी चालू वेळ O(1) का आहे ते दाखवू.

ॲड(व्हॅल्यू) ऑपरेशनच्या चालू वेळेचा अंदाज लावणे.

प्रथम त्या पर्यायाचा विचार करू ज्यामध्ये फक्त एका घटकाने ॲरे वाढवला आहे. या प्रकरणात, नवीन घटक जोडताना, प्रत्येक वेळी आपल्याला नवीन ॲरे तयार करावी लागेल आणि त्यामध्ये जुन्या घटकांची कॉपी करावी लागेल. अशा प्रकारे, ॲड(व्हॅल्यू) चा चालू वेळ नेहमी (सरासरीसह) O(N) च्या बरोबरीचा असेल. जरी आम्ही आमचा ॲरे प्रत्येक वेळी k घटकांद्वारे विस्तारित केला तरीही, सरासरी चालू वेळ अजूनही O(N) असेल. खरंच. प्रत्येक kth वेळी ऑपरेशन O(N), आणि इतर प्रकरणांमध्ये O(1) मध्ये केले जाते. जर आपण अंकगणिताची सरासरी घेतली तर आपल्याला C*N मिळेल, म्हणजेच O(N).

आता आपण एका वास्तविक केसचा विचार करूया ज्यामध्ये ॲरे प्रत्येक वेळी दीड पटीने लांब केला जातो. LinkedList प्रकारातील एक ऑब्जेक्ट भरा आकार घटक. शेवटचा घटक जोडण्यासाठी आपल्या ॲरेचा विस्तार करावा लागेल असे गृहीत धरू. ही वस्तू भरण्यासाठी किती वेळ लागला याची गणना करूया. घटकाच्या शेवटच्या जोडणीने आकाराच्या ऑपरेशन्स घेतल्या. मागील अनेक कॉल्समध्ये प्रत्येकी एक ऑपरेशन झाले. उपांत्य "दीर्घ" जोडणी अंदाजे (2/3)* आकाराची ऑपरेशन्स केली गेली (कारण ॲरे प्रत्येक वेळी दीड पटीने वाढतो). वगैरे. आम्हाला आढळले की एकूण ऑपरेशन्सची संख्या अंदाजे होती:

आकार + (2/3) * आकार + (2/3) 2 * आकार + (2/3) 3 * आकार + ... = आकार / (1 - 2/3) = 3 * आकार

म्हणजेच, आम्हाला समजले की ऑपरेशन ॲड(व्हॅल्यू) साइज पूर्ण होण्यासाठी C * आकार वेळ लागतो, याचा अर्थ ॲड(व्हॅल्यू) च्या अंमलबजावणीची वेळ O(1) आहे.

ArrayList मधील अतिरिक्त पद्धती .

ArrayList साठी आधीच शिकलेल्या पद्धती व्यतिरिक्त आणखी काही पद्धती आहेत ज्या जाणून घेण्यासाठी उपयुक्त आहेत: trimToSize() आणि खात्री कॅपॅसिटी(क्षमता). पहिली पद्धत ArrayList मधील पॅरामीटरद्वारे संग्रहित केलेल्या लांबीपर्यंत ॲरे कमी करते . म्हणजेच, ते वापरताना, ॲरेचे क्षुल्लक घटक सहजपणे काढले जातात. वापरताना "list.ensureCapacity(capacity);" ॲरेची लांबी किमान क्षमतेची होईल. या पद्धती लक्षात ठेवण्यासारख्या आहेत, परंतु त्यांना बर्याचदा आवश्यक नसते. या दोन्ही ऑपरेशन्स मेमरी वाचवतात आणि योग्यरित्या वापरल्यास कॅपॅसिटी (क्षमता) प्रोग्राम चालवण्याचा वेळ कमी करते याची खात्री करा.

तसेच, ArrayList क्लासचे ऑब्जेक्ट तयार करताना ॲरेची लांबी सेट केली जाऊ शकते . ॲरेची प्रारंभिक लांबी क्षमतेवर सेट करण्यासाठी, फक्त लिहा:

ArrayList list = नवीन ArrayList (क्षमता);

निष्कर्ष.

ArrayList वर्ग विहंगावलोकन आम्ही LinkedList वर्गाशी थोडी तुलना करून पूर्ण करू .

ArrayList मध्ये लिंक्डलिस्टमध्ये असताना सूची घटकांमध्ये यादृच्छिक प्रवेश सतत होतो - रेखीय साठी. या संदर्भात, ArrayList वर्गातील ऑब्जेक्ट वापरणे चांगले आहे . परंतु, आम्ही तुम्हाला पुन्हा चेतावणी देतो, तुम्ही get(i) सारखी ऑपरेशन्स वापरणे टाळावे. जर तुमच्याकडे get(i) कॉल बायपास करण्याची संधी असेल, तर या संधीचा फायदा घेणे चांगले.

जावा ही ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग भाषा आहे या वस्तुस्थितीमुळे, मेमरी जतन करण्याच्या लढ्यात कोणत्याही वर्गाला महत्त्वपूर्ण फायदा नाही. औपचारिकपणे ArrayList या संदर्भात जिंकली तरी (यात trimToSize सारखी वैशिष्ट्ये आहेत हे लक्षात घेऊन), हा फायदा नगण्य आहे.

लिंक्डलिस्ट चांगली गोष्ट अशी आहे की नवीन घटक जोडण्यासाठी किती वेळ लागेल हे आपल्याला नेहमी माहित असते. ArrayList मध्ये आम्ही फक्त नवीन घटक जोडण्यासाठी लागणाऱ्या वेळेच्या सरासरी मूल्याबद्दल बोलू शकतो.

ArrayList चा मुख्य तोटा या वर्गासाठी विशेष कार्ये कॉल करण्याची क्षमता ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंगच्या विचारसरणीशी विरोधाभासी आहे.



आम्ही वाचण्याची शिफारस करतो

वर