HashSet <T> बनाम शब्दकोश <K, V> यह खोज का समय है कि कोई वस्तु मौजूद है या नहीं


103
HashSet<T> t = new HashSet<T>();
// add 10 million items


Dictionary<K, V> t = new Dictionary<K, V>();
// add 10 million items.

किसकी .Containsविधि जल्दी लौट आएगी?

बस स्पष्ट करने के लिए, मेरी आवश्यकता है मेरे पास 10 मिलियन ऑब्जेक्ट्स हैं (ठीक है, वास्तव में तार) जो मुझे जांचने की आवश्यकता है कि क्या वे डेटा संरचना में मौजूद हैं। मैं कभी नहीं होगा।


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

जवाबों:


153

HashSet बनाम सूची बनाम शब्दकोश प्रदर्शन परीक्षण, यहाँ से लिया गया ।

1000000 ऑब्जेक्ट्स जोड़ें (डुप्लिकेट की जाँच किए बिना)

10000 के संग्रह की आधी वस्तुओं की जांच करता है

10000 के संग्रह की आधी वस्तुओं को हटा दें


9
महान विश्लेषण! ऐसा लगता है। शब्दकोश के लिए .Contains इतना तेज़ है कि ओपी के मामले में हैशसेट का उपयोग करने से कोई लाभ नहीं है।
एथरड्रैगन

2
हाँ, मैं ओपी के रूप में एक ही सवाल था मेरे पास पहले से ही एक शब्दकोश है जिसका उपयोग मैं अन्य कारणों से कर रहा हूं, और यह जानना चाहता हूं कि क्या मुझे ContainsKey का उपयोग करने के बजाय एक हैशसेट में बदलने से लाभ होगा। लगता है कि जवाब नहीं है क्योंकि दोनों इतनी जल्दी नहीं हैं।
फिस्टोफ्यूरी

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

यह उत्तर आपको यह नहीं बताता है कि हैशसेट और डिक्शनरी की पूर्णता कितनी है ... यह सब आपको बताता है कि वे दोनों एक सूची की तुलना में अधिक तेज़ हैं ... ठीक है ... हाँ! जाहिर है! हैशसेट 3 गुना तेज हो सकता है और आपको नहीं पता होगा क्योंकि संबंधित परीक्षण दोनों को " एक सूची की तुलना में तात्कालिक ..." के लिए नीचे गिरा दिया गया है ।
ब्रॉन्डहल

71

मुझे लगता है कि आप Dictionary<TKey, TValue>दूसरे मामले में मतलब है? HashTableएक गैर-सामान्य वर्ग है।

आपको अपनी वास्तविक आवश्यकताओं के आधार पर नौकरी के लिए सही संग्रह चुनना चाहिए। क्या आप वास्तव में प्रत्येक कुंजी को एक मूल्य पर मैप करना चाहते हैं ? यदि हां, तो उपयोग करें Dictionary<,>। यदि आप केवल एक सेट के रूप में इसके बारे में परवाह करते हैं, तो उपयोग करें HashSet<>

मैं मूल रूप से एक ही एल्गोरिथ्म का उपयोग करने के लिए मूल रूप से एक ही प्रदर्शन कर रहे हैं, मैं उम्मीद करता हूं HashSet<T>.Containsऔर Dictionary<TKey, TValue>.ContainsKey(जो तुलनीय संचालन कर रहे हैं, आप समझदारी से अपने शब्दकोश का उपयोग कर रहे हैं)। मैं में प्रविष्टियों के साथ लगता है कि Dictionary<,>बड़ा होने आप के साथ कैश उड़ाने की अधिक संभावना के साथ अंत Dictionary<,>के साथ तुलना में HashSet<>, लेकिन मैं उम्मीद थी कि बस आप क्या कर रहे हैं के मामले में गलत डेटा प्रकार को चुनने का दर्द के साथ तुलना में महत्वपूर्ण होने के लिए प्राप्त करने की कोशिश कर रहा है।


हां, मेरा मतलब डिक्शनरी <टीके, टीवीएल्यू> है। मैं केवल डेटा संरचना में आइटम के अस्तित्व की खोज करने के बारे में चिंतित हूं, यह सब है
हॉल्टिंगस्टोन

3
@halivingston उस मामले में हैशसेट का उपयोग करें। यह यह स्पष्ट है कि कि बनाता है आप सभी की जरूरत।
जॉन स्कीट

2
ठीक है धन्यवाद। मेरे पास वास्तव में एक HashSet <TKey> है, और शब्दकोश <Tkey, TValue> की एक डुप्लिकेट प्रति भी स्मृति में है। मैं पहले। HashSet पर आता हूं, फिर शब्दकोश <TKey, TValue> में मान को फिर से लिखता हूं। मेरे पास अभी असीम मेमोरी है, लेकिन जल्द ही मुझे डर है कि मेरी मेमोरी बाधित हो जाएगी और हमारी टीम मुझे मेमोरी में इस डुप्लिकेट सामान को हटाने के लिए कहेगी, जिस बिंदु पर मुझे डिक्शनरी <टीके, टीवीएल्यू> का उपयोग करने के लिए मजबूर किया जाएगा।
हॉल्टिंगस्टन

4
आपको पता है कि शब्दकोश में एक ContainsKey फ़ंक्शन भी सही है? आप डेटा की नकल क्यों कर रहे हैं?
ब्लाइंडी

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

7

शब्दकोश <TKey, TValue> के लिए MSDN प्रलेखन से

"इसकी कुंजी का उपयोग करके किसी मूल्य को प्राप्त करना बहुत तेज़ है, O (1) के करीब है , क्योंकि डिक्शनरी क्लास को एक हैशड टेबल के रूप में लागू किया गया है। "

एक नोट के साथ:

"पुनर्प्राप्ति की गति TKey के लिए निर्दिष्ट प्रकार के हैशिंग एल्गोरिथ्म की गुणवत्ता पर निर्भर करती है"

मुझे पता है कि आपका प्रश्न / पोस्ट पुराना है - लेकिन इसी तरह के एक प्रश्न के उत्तर की तलाश में मैं इस पर ठोकर खा गया।

उम्मीद है की यह मदद करेगा। अधिक विवरण के लिए नीचे टिप्पणी अनुभाग पर स्क्रॉल करें। https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx


4

ये अलग-अलग डेटा संरचनाएं हैं। इसके अलावा कोई सामान्य संस्करण नहीं है HashTable

HashSetटाइप T के मान हैं जिनमें HashTable(या Dictionary) कुंजी-मूल्य जोड़े हैं। इसलिए आपको संग्रह करना चाहिए कि आपको किस डेटा को संग्रहीत करने की आवश्यकता है।


0

इस सवाल का स्वीकृत उत्तर वैध रूप से प्रश्न का उत्तर नहीं देता है! यह सही उत्तर देने के लिए होता है, लेकिन यह उत्तर उनके द्वारा दिए गए सबूतों से नहीं दिखाया जाता है।

उस उत्तर से पता चलता है कि कुंजी देखने पर Dictionaryया किसी में देखने की HashSetतुलना में बहुत जल्दी है List। जो सच है, लेकिन दिलचस्प नहीं है, न ही आश्चर्य की बात है, और न ही सबूत है कि उनके पास समान गति है।

मैंने लुकअप समय की तुलना करने के लिए नीचे दिए गए कोड को चलाया है, और मेरा निष्कर्ष यह है कि वे वास्तव में समान गति वाले हैं। (या कम से कम, अगर कोई अंतर है, तो अंतर उस गति के मानक विचलन के भीतर अच्छी तरह से है)

विशेष रूप से, इस परीक्षण में, मेरे लिए, दोनों के लिए १०,०००,००० लुकअप १० से ११.५ सेकंड के बीच हो रहे थे।

टेस्ट कोड:

private const int TestReps = 100_000_000;
[Test]
public void CompareHashSetContainsVersusDictionaryContainsKey()
{
    for (int j = 0; j < 10; j++)
    {
        var rand = new Random();
        var dict = new Dictionary<int, int>();
        var hash = new HashSet<int>();

        for (int i = 0; i < TestReps; i++)
        {
            var key = rand.Next();
            var value = rand.Next();
            hash.Add(key);
            dict.TryAdd(key, value);
        }

        var testPoints = Enumerable.Repeat(1, TestReps).Select(_ => rand.Next()).ToArray();
        var timer = new Stopwatch();
        var total = 0;
        
        timer.Restart();
            for (int i = 0; i < TestReps; i++)
            {
                var newKey = testPoints[i];
                if (hash.Contains(newKey))
                {
                    total++;
                }
            }
        Console.WriteLine(timer.Elapsed);
        
        var target = total;
        Assert.That(total == target);
        

        timer.Restart();
            for (int i = 0; i < TestReps; i++)
            {
                var newKey = testPoints[i];
                if (dict.ContainsKey(newKey))
                {
                    total++;
                }
            }
        Console.WriteLine(timer.Elapsed);

        Assert.That(total == target * 2);
        Console.WriteLine("Set");
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.