खोज…


परिचय

TreeMap और TreeSet मूल जावा संग्रह हैं जिन्हें जावा 1.2 में जोड़ा गया है। TreeMap Map एक म्यूटेबल , ऑर्डर किया हुआ , Map कार्यान्वयन है। इसी तरह, TreeSet एक म्यूटेबल , ऑर्डर किया गया Set कार्यान्वयन है।

TreeMap को रेड-ब्लैक ट्री के रूप में लागू किया गया है, जो O(log n) एक्सेस समय प्रदान करता है। TreeSet एक का उपयोग कर कार्यान्वित किया जाता है TreeMap डमी मूल्यों के साथ।

दोनों संग्रह धागा-सुरक्षित नहीं हैं।

एक सरल जावा प्रकार का ट्रीपाइप

सबसे पहले, हम एक खाली नक्शा बनाते हैं, और उसमें कुछ तत्व डालते हैं:

जावा एसई 7
TreeMap<Integer, String> treeMap = new TreeMap<>();
जावा एसई 7
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
treeMap.put(10, "ten");
treeMap.put(4, "four");
treeMap.put(1, "one");
treeSet.put(12, "twelve");

एक बार जब हमारे पास कुछ तत्व होते हैं, तो हम कुछ ऑपरेशन कर सकते हैं:

System.out.println(treeMap.firstEntry()); // Prints 1=one
System.out.println(treeMap.lastEntry()); // Prints 12=twelve
System.out.println(treeMap.size()); // Prints 4, since there are 4 elemens in the map
System.out.println(treeMap.get(12)); // Prints twelve
System.out.println(treeMap.get(15)); // Prints null, since the key is not found in the map

हम या तो एक Iterator, या एक foreach पाश का उपयोग करके मैप तत्वों पर पुनरावृति कर सकते हैं। ध्यान दें कि प्रविष्टियाँ उनके प्राकृतिक क्रम के अनुसार मुद्रित होती हैं, न कि प्रविष्टि क्रम:

जावा एसई 7
for (Entry<Integer, String> entry : treeMap.entrySet()) {
    System.out.print(entry + " "); //prints 1=one 4=four 10=ten 12=twelve 
}
Iterator<Entry<Integer, String>> iter = treeMap.entrySet().iterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " "); //prints 1=one 4=four 10=ten 12=twelve 
}

एक सरल जावा प्रकार के ट्रीसेट

सबसे पहले, हम एक खाली सेट बनाते हैं, और उसमें कुछ तत्व डालते हैं:

जावा एसई 7
TreeSet<Integer> treeSet = new TreeSet<>();
जावा एसई 7
TreeSet<Integer> treeSet = new TreeSet<Integer>();
treeSet.add(10);
treeSet.add(4);
treeSet.add(1);
treeSet.add(12);

एक बार सेट में कुछ तत्व होने के बाद, हम कुछ ऑपरेशन कर सकते हैं:

System.out.println(treeSet.first()); // Prints 1
System.out.println(treeSet.last()); // Prints 12
System.out.println(treeSet.size()); // Prints 4, since there are 4 elemens in the set
System.out.println(treeSet.contains(12)); // Prints true
System.out.println(treeSet.contains(15)); // Prints false

हम या तो एक Iterator, या एक foreach पाश का उपयोग करके मैप तत्वों पर पुनरावृति कर सकते हैं। ध्यान दें कि प्रविष्टियाँ उनके प्राकृतिक क्रम के अनुसार मुद्रित होती हैं, न कि प्रविष्टि क्रम:

जावा एसई 7
for (Integer i : treeSet) {
    System.out.print(i + " "); //prints 1 4 10 12
}
Iterator<Integer> iter = treeSet.iterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " "); //prints 1 4 10 12
}

ट्रीपाइप / ट्रीस्टेट एक कस्टम जावा प्रकार का

चूंकि TreeMap एस और TreeSet ने अपनी प्राकृतिक व्यवस्था के अनुसार कुंजियों / तत्वों को बनाए रखा है। वहाँ के लिए TreeMap कुंजी और TreeSet तत्वों को एक दूसरे से तुलनीय है।

कहें कि हमारे पास एक कस्टम Person वर्ग है:

public class Person  {

    private int id;
    private String firstName, lastName;
    private Date birthday;

    //... Constuctors, getters, setters and various methods
}

अगर हम इसे TreeSet (या एक TreeSet में कुंजी) स्टोर करते हैं:

TreeSet<Person2> set = ...      
set.add(new Person(1,"first","last",Date.from(Instant.now())));

तब हम इस तरह के एक अपवाद में भागेंगे:

Exception in thread "main" java.lang.ClassCastException: Person cannot be cast to java.lang.Comparable
    at java.util.TreeMap.compare(TreeMap.java:1294)
    at java.util.TreeMap.put(TreeMap.java:538)
    at java.util.TreeSet.add(TreeSet.java:255)

इसे ठीक करने के लिए, आइए मान लें कि हम Person को उनकी आईडी ( private int id ) के आदेश के आधार पर आदेश देना चाहते हैं। हम इसे दो तरीकों में से एक में कर सकते हैं:

  1. एक समाधान Person को संशोधित करना है ताकि यह तुलनात्मक इंटरफ़ेस को लागू करे:

    public class Person implements Comparable<Person> {
        private int id;
        private String firstName, lastName;
        private Date birthday;
    
        //... Constuctors, getters, setters and various methods
    
        @Override
        public int compareTo(Person o) {
            return Integer.compare(this.id, o.id); //Compare by id
        }
    }
    
  2. एक अन्य समाधान TreeSet को एक तुलनित्र प्रदान करना है:

जावा एसई 8
TreeSet<Person> treeSet = new TreeSet<>((personA, personB) -> Integer.compare(personA.getId(), personB.getId()));
TreeSet<Person> treeSet = new TreeSet<>(new Comparator<Person>(){
    @Override
    public int compare(Person personA, Person personB) {
        return Integer.compare(personA.getId(), personB.getId());
    }
});

हालांकि, दोनों दृष्टिकोणों के लिए दो चेतावनी हैं:

  1. TreeSet / TreeMap में एक इंस्टेंस डालने के बाद ऑर्डर करने के लिए इस्तेमाल किए गए किसी भी फ़ील्ड को संशोधित नहीं करना बहुत महत्वपूर्ण है । उपरोक्त उदाहरण में, यदि हम उस व्यक्ति की id बदलते हैं जो पहले से ही संग्रह में सम्मिलित है, तो हम अप्रत्याशित व्यवहार में भाग सकते हैं।

  2. तुलना को ठीक से और लगातार लागू करना महत्वपूर्ण है। जवादोक के अनुसार:

कार्यान्वयनकर्ता को सभी x और y के लिए sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) सुनिश्चित करना होगा। (इसका तात्पर्य है कि x.compareTo(y) को एक अपवाद फेंकना चाहिए iff y.compareTo(x) एक अपवाद फेंकता है।)

कार्यान्वयनकर्ता को यह भी सुनिश्चित करना होगा कि संबंध सकर्मक है: (x.compareTo(y)>0 && y.compareTo(z)>0) का तात्पर्य x.compareTo(z)>0

अंत में, कार्यान्वयनकर्ता को यह सुनिश्चित करना चाहिए कि x.compareTo(y)==0 तात्पर्य है कि सभी z के लिए sgn(x.compareTo(z)) == sgn(y.compareTo(z))

ट्री मैप और ट्रीसेट थ्रेड सेफ्टी

TreeMap और TreeSet धागे की सुरक्षित संग्रह, इसलिए ध्यान जब मल्टी-थ्रेडेड कार्यक्रमों में इस्तेमाल सुनिश्चित करने के लिए लिया जाना चाहिए नहीं हैं।

TreeMap और TreeSet दोनों ही सुरक्षित हैं, जब पढ़े जाते हैं, समवर्ती रूप से, कई थ्रेड्स द्वारा। इसलिए यदि उन्हें एक ही धागे से बनाया और आबाद किया गया है (जैसे, कार्यक्रम की शुरुआत में), और उसके बाद ही पढ़ें, लेकिन कई थ्रेड्स द्वारा संशोधित नहीं किया गया है, तो सिंक्रनाइज़ेशन या लॉक करने का कोई कारण नहीं है।

हालाँकि, यदि पढ़ा और संशोधित किया गया समवर्ती, या एक से अधिक थ्रेड द्वारा समवर्ती रूप से संशोधित किया गया है, तो संग्रह एक समवर्तीModificationException को फेंक सकता है या अप्रत्याशित रूप से व्यवहार कर सकता है। इन मामलों में, निम्नलिखित में से किसी एक का उपयोग करके संग्रह तक पहुंच / लॉक को सिंक्रनाइज़ करना अत्यावश्यक है:

  1. Collections.synchronizedSorted.. का उपयोग कर Collections.synchronizedSorted..

    SortedSet<Integer> set = Collections.synchronizedSortedSet(new TreeSet<Integer>());
    SortedMap<Integer,String> map = Collections.synchronizedSortedMap(new TreeMap<Integer,String>());
    

    यह वास्तविक संग्रह द्वारा समर्थित SortedSet / SortedMap कार्यान्वयन प्रदान करेगा, और कुछ म्यूटेक्स ऑब्जेक्ट पर सिंक्रनाइज़ किया जाएगा। ध्यान दें कि यह एक ही लॉक पर संग्रह तक सभी पढ़ने और लिखने के लिए सिंक्रनाइज़ करेगा, इसलिए समवर्ती रीड भी संभव नहीं होगा।

  2. किसी वस्तु पर मैन्युअल रूप से सिंक्रनाइज़ करके, जैसे कि संग्रह:

     TreeSet<Integer> set = new TreeSet<>(); 
    

    ...

    //Thread 1
    synchronized (set) {
        set.add(4);
    }
    

    ...

    //Thread 2
    synchronized (set) {
        set.remove(5);
    }        
    
  3. एक ताला का उपयोग करके, जैसे कि एक ReentrantReadWriteLock :

     TreeSet<Integer> set = new TreeSet<>(); 
     ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    

    ...

     //Thread 1
     lock.writeLock().lock();
     set.add(4);
     lock.writeLock().unlock();
    

    ...

     //Thread 2
     lock.readLock().lock();
     set.contains(5);
     lock.readLock().unlock();
    

जैसा कि पिछले सिंक्रनाइज़ेशन विधियों के विपरीत है, ReadWriteLock का उपयोग करके कई थ्रेड को मानचित्र से समवर्ती रूप से पढ़ने की अनुमति देता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow