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

ट्री मैप क्या है ? यह एक शब्दकोश-जैसी डेटा संरचना है जो तत्वों को कुंजी-मूल्य जोड़े के रूप में संग्रहीत करती है, उन्हें कुंजी द्वारा क्रमबद्ध करती है।

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

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


public class Person implements Comparable<Person> {
 
    private String firstName;
    private String lastName;
 
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
  …
 
    @Override
    public int compareTo(Person person) {
        return person.getFirstName().compareTo(firstName);
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}

चलिए तुलना करने के लिए () विधि को ओवरराइड करते हैं ताकि यह मूल्यों को पहले नाम से उल्टे वर्णानुक्रम में क्रमबद्ध कर सके:


TreeMap map = new TreeMap<Person, String>();
 
map.put(new Person("AA","BB"), "aa");
map.put(new Person("BB","BB"), "aa");
map.put(new Person("DD","BB"), "aa");
map.put(new Person("CC","BB"), "aa");

मान निम्न क्रम में संग्रहीत किए जाएंगे:


Person{firstName='DD', lastName='BB'}
Person{firstName='CC', lastName='BB'}
Person{firstName='BB', lastName='BB'}
Person{firstName='AA', lastName='BB'}

TreeMap वर्ग नेविगेबल मैप इंटरफ़ेस को लागू करता है, जो बदले में सॉर्टेड मैप इंटरफ़ेस का विस्तार करता है । यह TreeMap वर्ग को क्रमबद्ध क्रम में मूल्यों को संग्रहीत करने के लिए पेड़ों का उपयोग करने देता है।

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

इसे सरल शब्दों में कहें तो, एक लाल-काला पेड़ एक डेटा संरचना है जो मूल्यों को सही सबट्री में संग्रहीत करता है यदि वे रूट से अधिक हैं, और बाएं सबट्री में यदि वे कम हैं। यह कार्यान्वयन संरचना में मूल्यों को बहुत तेज़ी से देख सकता है।

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

खैर, अब आप जानते हैं कि ट्री मैप क्या है और यह कैसे काम करता है।

याद रखें कि TreeMap केवल उन वस्तुओं को संग्रहीत कर सकता है जिनकी कक्षा तुलनात्मक इंटरफ़ेस लागू करती है और तुलना करने के लिए () विधि को ओवरराइड करती है।

लेकिन क्या होगा अगर हम विभिन्न पुस्तकालयों से लोड किए गए तृतीय-पक्ष वर्गों का उपयोग कर रहे हैं और उनमें तुलनात्मक लागू नहीं कर सकते हैं? इसके लिए एक समाधान है: अपना तुलनित्र लिखें ।

तुलनित्र एक इंटरफ़ेस है जिसमें एक तुलना () विधि है। हम इसका उपयोग वस्तुओं की तुलना करने और उन्हें TreeMap में संग्रहीत करने के लिए कर सकते हैं ।


Comparator<Person> comparator = new Comparator<Person>() {
 
    @Override
    public int compare(Person person1, Person person2) {
        return person1.getFirstName().compareTo(person2.getFirstName());
    }
};
 
 
TreeMap map = new TreeMap<Person, String>(comparator);

इस उदाहरण में, हमने एक कस्टम तुलनित्र बनाया और एक ट्रीमैप को कक्षा में पास किया।

जावा 8 से शुरू होकर, हम इसे लैम्ब्डा एक्सप्रेशन का उपयोग करके लिख सकते हैं:


TreeMap map = new TreeMap<Person, String>((Person person1, Person person2) -> person1.getFirstName().compareTo(person2.getFirstName()));

दूसरे शब्दों में, TreeMap में मानों को संग्रहीत करने के लिए , आपको यह निर्दिष्ट करने की आवश्यकता है कि उन्हें कैसे क्रमबद्ध किया जाए। ऐसा करने के दो तरीके हैं: Comparable लागू करें या अपना खुद का Comparator लागू करें ।

लेकिन क्या होगा अगर हमें एक ट्रीमैप में एक कुंजी के रूप में नल डालने की आवश्यकता है? हैश मैप आपको ऐसा करने देता है। हाँ, लेकिन TreeMap इसे कैसे संभालता है?


TreeMap map = new TreeMap<Person, String>();
map.put (null, "Person");

इस कोड को चलाना हमें एक त्रुटि देता है:

धागे में अपवाद "मुख्य" java.lang.NullPointerException java.base/java.util.TreeMap.put पर (TreeMap.java:561)

समस्या यह है कि आंतरिक रूप से TreeMap वर्ग तुलना() विधि का उपयोग करके मूल्यों की तुलना करता है। आप निश्चित रूप से शून्य मान में पास कर सकते हैं और कोड संकलित होगा। लेकिन रनटाइम पर आपको एक त्रुटि मिलेगी, क्योंकि विधि को शून्य मान पर कॉल किया जाएगा, जिससे NullPointerException को फेंक दिया जाएगा।

हैश मैप और ट्री मैप की तुलना

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

आपके पास यह है - अब आप जानते हैं कि सॉर्ट किए गए क्रम में मूल्यों को संग्रहीत करने के लिए क्या उपयोग करना है, और सॉर्टिंग के लिए नियम कैसे सेट करें।