Java Language
ट्री मैप और ट्रीसेट
खोज…
परिचय
TreeMap
और TreeSet
मूल जावा संग्रह हैं जिन्हें जावा 1.2 में जोड़ा गया है। TreeMap
Map
एक म्यूटेबल , ऑर्डर किया हुआ , Map
कार्यान्वयन है। इसी तरह, TreeSet
एक म्यूटेबल , ऑर्डर किया गया Set
कार्यान्वयन है।
TreeMap
को रेड-ब्लैक ट्री के रूप में लागू किया गया है, जो O(log n)
एक्सेस समय प्रदान करता है। TreeSet
एक का उपयोग कर कार्यान्वित किया जाता है TreeMap
डमी मूल्यों के साथ।
दोनों संग्रह धागा-सुरक्षित नहीं हैं।
एक सरल जावा प्रकार का ट्रीपाइप
सबसे पहले, हम एक खाली नक्शा बनाते हैं, और उसमें कुछ तत्व डालते हैं:
TreeMap<Integer, String> treeMap = new TreeMap<>();
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 पाश का उपयोग करके मैप तत्वों पर पुनरावृति कर सकते हैं। ध्यान दें कि प्रविष्टियाँ उनके प्राकृतिक क्रम के अनुसार मुद्रित होती हैं, न कि प्रविष्टि क्रम:
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
}
एक सरल जावा प्रकार के ट्रीसेट
सबसे पहले, हम एक खाली सेट बनाते हैं, और उसमें कुछ तत्व डालते हैं:
TreeSet<Integer> treeSet = new TreeSet<>();
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 पाश का उपयोग करके मैप तत्वों पर पुनरावृति कर सकते हैं। ध्यान दें कि प्रविष्टियाँ उनके प्राकृतिक क्रम के अनुसार मुद्रित होती हैं, न कि प्रविष्टि क्रम:
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
) के आदेश के आधार पर आदेश देना चाहते हैं। हम इसे दो तरीकों में से एक में कर सकते हैं:
एक समाधान
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 } }
एक अन्य समाधान
TreeSet
को एक तुलनित्र प्रदान करना है:
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());
}
});
हालांकि, दोनों दृष्टिकोणों के लिए दो चेतावनी हैं:
TreeSet
/TreeMap
में एक इंस्टेंस डालने के बाद ऑर्डर करने के लिए इस्तेमाल किए गए किसी भी फ़ील्ड को संशोधित नहीं करना बहुत महत्वपूर्ण है । उपरोक्त उदाहरण में, यदि हम उस व्यक्ति कीid
बदलते हैं जो पहले से ही संग्रह में सम्मिलित है, तो हम अप्रत्याशित व्यवहार में भाग सकते हैं।तुलना को ठीक से और लगातार लागू करना महत्वपूर्ण है। जवादोक के अनुसार:
कार्यान्वयनकर्ता को सभी x और y के लिए
sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
सुनिश्चित करना होगा। (इसका तात्पर्य है किx.compareTo(y)
को एक अपवाद फेंकना चाहिए iffy.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 को फेंक सकता है या अप्रत्याशित रूप से व्यवहार कर सकता है। इन मामलों में, निम्नलिखित में से किसी एक का उपयोग करके संग्रह तक पहुंच / लॉक को सिंक्रनाइज़ करना अत्यावश्यक है:
Collections.synchronizedSorted..
का उपयोग करCollections.synchronizedSorted..
SortedSet<Integer> set = Collections.synchronizedSortedSet(new TreeSet<Integer>()); SortedMap<Integer,String> map = Collections.synchronizedSortedMap(new TreeMap<Integer,String>());
यह वास्तविक संग्रह द्वारा समर्थित SortedSet / SortedMap कार्यान्वयन प्रदान करेगा, और कुछ म्यूटेक्स ऑब्जेक्ट पर सिंक्रनाइज़ किया जाएगा। ध्यान दें कि यह एक ही लॉक पर संग्रह तक सभी पढ़ने और लिखने के लिए सिंक्रनाइज़ करेगा, इसलिए समवर्ती रीड भी संभव नहीं होगा।
किसी वस्तु पर मैन्युअल रूप से सिंक्रनाइज़ करके, जैसे कि संग्रह:
TreeSet<Integer> set = new TreeSet<>();
...
//Thread 1 synchronized (set) { set.add(4); }
...
//Thread 2 synchronized (set) { set.remove(5); }
एक ताला का उपयोग करके, जैसे कि एक 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 का उपयोग करके कई थ्रेड को मानचित्र से समवर्ती रूप से पढ़ने की अनुमति देता है।