जावा में एक अद्वितीय सूची कैसे बनाए रखें?


104

जावा में अद्वितीय / विशिष्ट वस्तुओं (कोई डुप्लिकेट) की सूची कैसे बनाएं?

अभी मैं HashMap<String, Integer>ऐसा करने के लिए उपयोग कर रहा हूं क्योंकि कुंजी को अधिलेखित कर दिया गया है और इसलिए अंत में हम प्राप्त कर सकते हैं HashMap.getKeySet()जो अद्वितीय होगा। लेकिन मुझे यकीन है कि ऐसा करने का एक बेहतर तरीका होना चाहिए क्योंकि मूल्य भाग यहां बर्बाद हो गया है।

जवाबों:


164

आप एक सेट कार्यान्वयन का उपयोग कर सकते हैं :

JAVADoc से कुछ जानकारी:

एक संग्रह जिसमें कोई डुप्लिकेट तत्व नहीं हैं । औपचारिक रूप से, सेट में तत्वों की कोई जोड़ी नहीं होती है e1 और e2 जैसे कि e1.equals (e2), और अधिकांश एक शून्य तत्व पर। जैसा कि इसके नाम से निहित है, यह इंटरफ़ेस गणितीय सेट अमूर्त मॉडल है।

ध्यान दें: महान देखभाल का उपयोग किया जाना चाहिए यदि उत्परिवर्तित वस्तुओं को सेट तत्वों के रूप में उपयोग किया जाता है। एक सेट का व्यवहार निर्दिष्ट नहीं है यदि किसी ऑब्जेक्ट का मूल्य इस तरह से बदल दिया जाता है जो समान तुलना को प्रभावित करता है जबकि ऑब्जेक्ट सेट में एक तत्व है। इस निषेध का एक विशेष मामला यह है कि यह एक सेट के लिए खुद को एक तत्व के रूप में स्वीकार्य नहीं है। `

ये कार्यान्वयन हैं:

  • HashSet

    यह वर्ग मूल संचालन के लिए निरंतर समय प्रदर्शन प्रदान करता है (जोड़ें, हटाएं, होता है और आकार), मान लें कि हैश फ़ंक्शन बाल्टी के बीच तत्वों को ठीक से फैलाता है। इस सेट पर Iterating को HashSet इंस्टेंस के आकार (तत्वों की संख्या) के साथ-साथ बैकिंग HashMap उदाहरण (बाल्टी की संख्या) की "क्षमता" के अनुपात में समय की आवश्यकता होती है। इस प्रकार, यह बहुत महत्वपूर्ण है कि यदि प्रारंभिक प्रदर्शन महत्वपूर्ण है, तो प्रारंभिक क्षमता बहुत अधिक (या लोड फैक्टर बहुत कम) निर्धारित न करें।

    जब उपज HashSetतत्वों के क्रम को पुनरावृत्त करना अपरिभाषित होता है।

  • LinkedHashSet

    हेश टेबल और सेट इट इंटरफ़ेस की लिंक्ड सूची कार्यान्वयन, पूर्वानुमानित पुनरावृत्ति क्रम के साथ। यह कार्यान्वयन हैशसेट से इस मायने में भिन्न है कि यह अपनी सभी प्रविष्टियों के माध्यम से चलने वाली एक डबल-लिंक्ड सूची को बनाए रखता है। यह लिंक की गई सूची पुनरावृत्ति क्रम को परिभाषित करती है, जो वह क्रम है जिसमें तत्वों को सेट (सम्मिलन-क्रम) में डाला गया था। ध्यान दें कि अगर किसी तत्व को सेट में फिर से डाला जाता है तो सम्मिलन आदेश प्रभावित नहीं होता है। (एक तत्व ई को एक सेट s में बदल दिया जाता है, अगर s.add (e) तब आह्वान किया जाता है जब s.contains (e) आह्वान के तुरंत पहले सच हो जाता है।)

    तो, ऊपर दिए गए कोड का आउटपुट ...

     Set<Integer> linkedHashSet = new LinkedHashSet<>();
     linkedHashSet.add(3);
     linkedHashSet.add(1);
     linkedHashSet.add(2);
    
     for (int i : linkedHashSet) {
         System.out.println(i);
     }
    

    ... जरूरी होगा

    3
    1
    2
    
  • TreeSet

    यह कार्यान्वयन बुनियादी कार्यों के लिए गारंटीकृत लॉग (एन) समय लागत प्रदान करता है (जोड़ें, हटाएं और शामिल करें)। डिफ़ॉल्ट रूप से वह पुनरावृति पर लौटे तत्वों को उनके " प्राकृतिक क्रम " द्वारा क्रमबद्ध किया जाता है , इसलिए ऊपर कोड ...

     Set<Integer> treeSet = new TreeSet<>();
     treeSet.add(3);
     treeSet.add(1);
     treeSet.add(2);
    
     for (int i : treeSet) {
         System.out.println(i);
     }
    

    ... यह उत्पादन होगा:

    1
    2
    3
    

    (आप Comparatorएक TreeSetनिर्माता को एक उदाहरण भी दे सकते हैं , जिससे तत्वों को एक अलग क्रम में क्रमबद्ध किया जा सकता है।)

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


अब मैं असमंजस में हूं, कि मैं किसका उपयोग करूं? मुझे केवल अद्वितीय तारों की एक सूची बनाए रखने की आवश्यकता है। तो मूल रूप से तब भी जब एक मौजूदा तार जोड़ा जाता है, इसे वास्तव में जोड़ा जाना चाहिए।

1
पसंद आपकी है ... हैशटैट्स यूनिवर्सल और फास्ट है, ट्रीसेट ऑर्डर किया गया है, लिंक्ड हैशसेट इंसर्शन ऑर्डर जारी रखता है ...
फ्रैंक

6
यह कोई LIST नहीं है ... इसलिए, सभी LIST इंटरफ़ेस विधियाँ उपलब्ध नहीं हैं।
मार्कोलोप्स

2
एक सेट एक सूची नहीं है, मैं O (1) समय (रैंडम एक्सेस) में एक सेट में सूचकांक द्वारा तत्वों को नहीं देख सकता।
विल्मॉल

13

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

यदि आपको वास्तव में एक सूची की आवश्यकता है जिसमें बस एक अद्वितीय बाधा है, तो Apache Common Utils class org.apache.commons.collections.list.SetUniqueList है जो आपको सूची इंटरफ़ेस और अद्वितीय बाधा प्रदान करेगा। ध्यान रहे, यह सूची इंटरफ़ेस को तोड़ता है। हालाँकि, यदि आपको सूची में अनुक्रमणिका की तलाश करने की आवश्यकता है, तो इससे बेहतर प्रदर्शन प्राप्त करेंगे। यदि आप सेट इंटरफ़ेस से निपट सकते हैं, और आपके पास एक छोटा डेटा सेट है, तो LinkedHashSet जाने का एक अच्छा तरीका हो सकता है। यह सिर्फ आपके सॉफ्टवेयर के डिजाइन और इरादे पर निर्भर करता है।

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


3
यह प्रश्न का उत्तर प्रदान नहीं करता है। किसी लेखक से स्पष्टीकरण मांगने या उसका अनुरोध करने के लिए, उनके पोस्ट के नीचे एक टिप्पणी छोड़ दें - आप हमेशा अपने स्वयं के पोस्ट पर टिप्पणी कर सकते हैं, और एक बार आपके पास पर्याप्त प्रतिष्ठा होने पर आप किसी भी पोस्ट पर टिप्पणी करने में सक्षम होंगे ।
Zach Saucier

1
यह वास्तव में एक उत्तर प्रदान करता है। यदि वह सिर्फ एक सूची चाहता है जो एक सेट की तरह काम करता है, तो org.apache.commons.collections.list.SetUniqueList का उपयोग करें, लेकिन एक प्रोग्रामर के रूप में, वह / हमें उससे अधिक सावधान रहना चाहिए और समस्या के बारे में अधिक सोचना चाहिए। यदि यह मेरे उत्तर को बेहतर बनाता है, "जावा में एक अनूठी सूची कैसे बनाएं?" सूची अद्वितीय सूची = नया सेट-यूनीकलिस्ट (?), यह है कि कैसे ....
पॉल कॉनॉली

3
और Zach, मैं एक झटका बनने की कोशिश नहीं कर रहा हूं, लेकिन क्या आपने अपनी टिप्पणी से पहले मेरा जवाब भी पढ़ा है? या आप बस इसे नहीं समझते हैं? यदि आप इसे नहीं समझते हैं, तो यह ठीक है - मुझे बताएं और मैं इस विषय पर विस्तार करूंगा। मुझे नहीं लगता कि किसी के प्रश्न का मैत्रीपूर्ण उत्तर देने के लिए मुझे डेटा संरचनाओं पर एक ग्रंथ लिखना चाहिए। न ही मुझे इस बात का ध्यान है कि मैं अपनी टिप्पणी प्रतिष्ठा के निर्माण के बारे में कुछ विनम्र तरीके से जाऊं जब मुझे इसका उत्तर पता हो और किसी और ने वास्तव में इसे प्रदान नहीं किया हो।
पॉल कोनोली

1
और वैसे भी, मैं न तो आलोचक था और न ही लेखक से स्पष्टीकरण का अनुरोध करता था, मैं सिर्फ यह कह रहा था कि वह या तो ए) मैं जिस क्लास को दे सकता हूं उसे जल्दी से इस्तेमाल करूं, या बी) इन कक्षाओं के बीच के अंतरों को समझने और संबंध बनाने के लिए समय लेता हूं उनकी जरूरतों के लिए। बी स्पष्ट रूप से अधिक समय लेता है, लेकिन लंबे समय में बेहतर कोड होगा।
पॉल कॉनटोली

8

new HashSet<String> एक उदाहरण का उपयोग करें :

import java.util.HashSet;
import java.util.Set;

public class MainClass {
  public static void main(String args[]) {
    String[] name1 = { "Amy", "Jose", "Jeremy", "Alice", "Patrick" };

    String[] name2 = { "Alan", "Amy", "Jeremy", "Helen", "Alexi" };

    String[] name3 = { "Adel", "Aaron", "Amy", "James", "Alice" };

    Set<String> letter = new HashSet<String>();

    for (int i = 0; i < name1.length; i++)
      letter.add(name1[i]);

    for (int j = 0; j < name2.length; j++)
      letter.add(name2[j]);

    for (int k = 0; k < name3.length; k++)
      letter.add(name3[k]);

    System.out.println(letter.size() + " letters must be sent to: " + letter);

  }
}

2
बस उपरोक्त कार्यक्रम के पुट को जोड़ते हुए -> 11 पत्र भेजे जाने चाहिए: [हारून, ऐलिस, जेम्स, एडेल, जोस, जेरेमी, एमी, एलन, पैट्रिक, हेलेन, अलेक्सी]
Ammad

4

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


3

HashSet<String>(या) कोई भी Setकार्यान्वयन आपके लिए काम कर सकता है। Setडुप्लिकेट की अनुमति न दें।

यहाँ हैशसेट के लिए javadoc है।


2

मुझे नहीं पता कि यह कितना कुशल है, हालांकि मेरे लिए एक साधारण संदर्भ में काम किया है।

List<int> uniqueNumbers = new ArrayList<>();

   public void AddNumberToList(int num)
    {
        if(!uniqueNumbers .contains(num)) {
            uniqueNumbers .add(num);
        }
    }

1

आप java.util.Set<E>इंटरफ़ेस के कार्यान्वयन वर्ग जैसे java.util.HashSet<String> संग्रह श्रेणी में से किसी एक का उपयोग करना चाह सकते हैं ।

एक संग्रह जिसमें कोई डुप्लिकेट तत्व नहीं हैं। औपचारिक रूप से, सेट में तत्वों की कोई जोड़ी नहीं होती है e1 और e2 जैसे कि e1.equals (e2), और अधिकांश एक शून्य तत्व पर। जैसा कि इसके नाम से निहित है, यह इंटरफ़ेस गणितीय सेट अमूर्त मॉडल है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.