2010-02-26 16 views
23

मैं एक कैश-इजेक्ट विधि है कि अनिवार्य रूप से इस तरह दिखता है लिख रहा हूँ:<Collection> है। उपयोग करने के लिए महंगा है?

while (myHashSet.Count > MAX_ALLOWED_CACHE_MEMBERS) 
{ 
    EjectOldestItem(myHashSet); 
} 

मेरा प्रश्न Count कैसे निर्धारित किया जाता है के बारे में है: यह सिर्फ एक private या protected int है, या यह तत्व एक गिनती की जाती है समय कहा जाता है?

+4

अच्छा सवाल। मैं एक आंतरिक int की आशा करता हूं, क्योंकि ज्यादातर मामलों में यह करना काफी आसान होगा, लेकिन मुझे नहीं पता। – Tarka

उत्तर

41

http://msdn.microsoft.com/en-us/library/ms132433.aspx से:

इस संपत्ति का मूल्य एक प्राप्त कर रहा है हे (1) ऑपरेशन है।

यह गारंटी देता है कि Count तक पहुंचने से पूरे संग्रह में पुन: प्रयास नहीं होगा।


संपादित करें: के रूप में कई अन्य पोस्टर का सुझाव दिया, IEnumerable<...>.Count() तथापि है नहीं हे होने की गारंटी (1)। देखभाल के साथ प्रयोग करें!

IEnumerable<...>.Count() एक विस्तार विधि System.Linq.Enumerable में परिभाषित किया गया है। वर्तमान कार्यान्वयन एक स्पष्ट परीक्षण करता है, तो गिना IEnumerable<T> वास्तव में ICollection<T> का एक उदाहरण है, और ICollection<T>.Count का उपयोग करता है यदि संभव हो तो। अन्यथा यह IEnumerable<T> (संभावित आलसी मूल्यांकन का विस्तार करने) को पार करता है और वस्तुओं को एक-एक करके गिना जाता है।

हालांकि मुझे दस्तावेज में नहीं मिला है कि क्या यह गारंटी है कि IEnumerable<...>.Count() यदि संभव हो तो ओ (1) का उपयोग करता है, मैंने केवल प्रतिबिंबक के साथ .NET 3.5 में कार्यान्वयन की जांच की है।


आवश्यक देर अलावा: कई लोकप्रिय कंटेनरों Collection<T> से प्राप्त कर रहे नहीं, लेकिन फिर भी उनके Count संपत्ति हे (1) है (जो है, पूरे संग्रह से अधिक पुनरावृति नहीं होगा)। उदाहरण HashSet<T>.Count (यह सबसे अधिक संभावना है कि ओपी क्या पूछना चाहता था), Dictionary<K, V>.Count, LinkedList<T>.Count, List<T>.Count, Queue<T>.Count, Stack<T>.Count और इसी तरह।

इन सभी संग्रह ICollection<T> है या सिर्फ ICollection लागू है, इसलिए उनके CountICollection<T>.Count (या ICollection.Count) के एक कार्यान्वयन है। प्रलेखन के अनुसार ICollection<T>.Count के कार्यान्वयन के लिए यह आवश्यक नहीं है कि ओ (1) ऑपरेशन हो, लेकिन ऊपर वर्णित लोग इस तरह से कर रहे हैं।

(एक तरफ ध्यान दें: कुछ कंटेनर, उदाहरण के लिए, Queue<T> के लिए, लागू गैर सामान्य ICollection नहीं बल्कि ICollection<T>, तो वे "वारिस" केवल ICollection से से Count संपत्ति।)

+2

अपनी खुद की सलाह लेनी चाहिए और संग्रह को पढ़ना चाहिए। केवल सूची की तुलना करें। गणना दस्तावेज़! धन्यवाद। –

+0

@ बॉब: आपका स्वागत है। – Vlad

+5

कृपया ध्यान दें कि एक गणना() एक्सटेंशन विधि भी है जो IENumerables पर काम करती है। यह * नहीं * ओ (1) होने की गारंटी है। –

4

एक HashSet के मामले में यह सिर्फ एक आंतरिक int क्षेत्र और यहां तक ​​कि SortedSet (एक द्विआधारी पेड़ आधारित .net 4 के लिए सेट) एक आंतरिक क्षेत्र में अपनी गणना है।

7

यह एक आंतरिक मूल्य है, और गणना की नहीं है। documentation बताता है कि मान प्राप्त करना ओ (1) ऑपरेशन है।

1

यह एक आंतरिक int है जो प्रत्येक बार संग्रह में एक नया आइटम जोड़ा जाता है, तो वृद्धि हुई है।

9

आपका प्रश्न एक विशिष्ट संग्रह वर्ग तो ...

यह संग्रह वर्ग पर निर्भर करता है निर्दिष्ट नहीं है। ArrayList में एक आंतरिक चर है जो गणना करता है, जैसा कि सूची करता है। हालांकि, यह कार्यान्वयन विशिष्ट है, और संग्रह के प्रकार के आधार पर, यह प्रत्येक कॉल पर सैद्धांतिक रूप से पुन: गणना कर सकता है।

+1

हां। कक्षा "संग्रह" पर यह ओ (1) दस्तावेज़ राज्य के रूप में है। यदि आप आईसीओलेक्शन इंटरफ़ेस के बारे में बात कर रहे हैं, तो यह वास्तव में कार्यान्वयन पर निर्भर करता है। –

+4

@ जॉन - यह कहना मुश्किल है कि उन्होंने शीर्षक कैसे कहा। किसी भी संग्रह वर्ग के लिए एक सामान्य प्लेसहोल्डर होने का मतलब था, या यह वास्तविक "संग्रह" वर्ग होने का इरादा था। – Nick

6

जैसा कि अन्य ने ध्यान दिया है, संग्रह को संशोधित करते समय गणना बनाए रखा जाता है। फ्रेमवर्क में प्रत्येक संग्रह प्रकार के साथ यह लगभग हमेशा मामला है। यह एक IENumerable पर गणना विस्तार विधि का उपयोग करने से काफी अलग है जो प्रत्येक बार संग्रह की गणना करेगा।

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

+0

+1 यह निर्दिष्ट करने के लिए कि IENumerable <>। गणना() एक्सटेंशन विधि अलग है। निस्संदेह, विस्तार विधि कुछ जांचने के लिए जांच करती है कि क्या गणना करने से पहले गणना करने वाला एक ओ (1) गिनती वाला संग्रह है, लेकिन निश्चित रूप से कुछ ध्यान में रखना है। – Tanzelax

3

परावर्तक के अनुसार, यह के रूप में

public int Count{ get; } 

इसलिए यह व्युत्पन्न प्रकार

2

बस एक क्विक नोट द्वारा परिभाषित किया गया है कार्यान्वित किया जाता है। सावधान रहें कि .NET 3.5 में संग्रह को गिनने के दो तरीके हैं जब System.Linq का उपयोग किया जाता है। सामान्य संग्रह के लिए, पहले विकल्प को अन्य उत्तरों में पहले से वर्णित कारणों के लिए, गणना संपत्ति का उपयोग करना चाहिए।

LINQCount() एक्सटेंशन विधि के माध्यम से एक वैकल्पिक विधि भी उपलब्ध है। .Count() के बारे में दिलचस्प बात यह है कि इसे किसी भी गणना पर कहा जा सकता है, भले ही अंतर्निहित वर्ग आईसीओलेक्शन लागू करता है या नहीं, या उसके पास गणना की गई संपत्ति है या नहीं। यदि आप कभी कॉल करते हैं। गणना() हालांकि, इस बात से अवगत रहें कि यह गणना को गतिशील रूप से गिनती उत्पन्न करने के लिए पुन: सक्रिय करेगा। आमतौर पर ओ (एन) जटिलता में परिणाम होता है।

इंटेलिसेन्स का उपयोग करने का एकमात्र कारण यह है कि गिनती संपत्ति के बजाय गिनती() एक्सटेंशन का उपयोग करना गलती से खत्म करना आसान होता है।

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