CodeGym /Java Blog /अनियमित /जावा में स्ट्रिंग और बराबर की तुलना करें
John Squirrels
स्तर 41
San Francisco

जावा में स्ट्रिंग और बराबर की तुलना करें

अनियमित ग्रुप में प्रकाशित
नमस्ते! आज हम एक बहुत ही महत्वपूर्ण और रोचक विषय के बारे में बात करेंगे, अर्थात्, वस्तुओं की वस्तुओं से तुलना (तुलना स्ट्रिंग्स और बराबर)। तो जावा में, ऑब्जेक्ट ऑब्जेक्ट बी के बराबर कब होगा ? आइए एक उदाहरण लिखने का प्रयास करें:

public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {
      
       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
कंसोल आउटपुट: झूठा रुको, रुको। ऐसा क्यों है कि ये दोनों कारें बराबर नहीं हैं? हमने उन्हें समान गुण दिए, लेकिन तुलना का परिणाम गलत है। उत्तर सीधा है। == ऑपरेटर ऑब्जेक्ट संदर्भों की तुलना करता है, ऑब्जेक्ट गुणों की नहीं दो वस्तुओं में समान मूल्यों के साथ 500 क्षेत्र भी हो सकते हैं, लेकिन उनकी तुलना करने से फिर भी झूठा निकलेगा। आखिरकार, कार 1 और कार 2 का संदर्भदो अलग-अलग वस्तुओं की ओर इशारा करें, यानी दो अलग-अलग पतों की ओर। ऐसी स्थिति की कल्पना करें जहां आप लोगों की तुलना कर रहे हों। निश्चित रूप से, दुनिया में कहीं कोई ऐसा व्यक्ति है जो आपके समान नाम, आंखों का रंग, आयु, ऊंचाई, बालों का रंग, आदि साझा करता है। यह आपको कई मामलों में समान बनाता है, लेकिन आप अभी भी जुड़वां नहीं हैं - और आप स्पष्ट रूप से नहीं हैं वही व्यक्ति।
बराबर और स्ट्रिंग तुलना - 2
जब हम दो वस्तुओं की तुलना करने के लिए इसका उपयोग करते हैं तो == ऑपरेटर लगभग इसी तर्क का उपयोग करता है। लेकिन क्या होगा यदि आपको अपने प्रोग्राम को विभिन्न तर्कों का उपयोग करने की आवश्यकता है? उदाहरण के लिए, मान लीजिए कि आपका प्रोग्राम डीएनए विश्लेषण करता है। यह दो लोगों के आनुवंशिक कोड की तुलना करता है और निर्धारित करता है कि क्या वे जुड़वां हैं।

public class Man {

   int geneticCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.geneticCode = 1111222233;

       Man man2 = new Man();
       man2.geneticCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
कंसोल आउटपुट: गलत हमें एक ही तार्किक परिणाम मिलता है (क्योंकि हम ज्यादा नहीं बदले), लेकिन अब वह तर्क अच्छा नहीं है! आखिरकार, वास्तविक जीवन में, डीएनए विश्लेषण से हमें 100% गारंटी मिलनी चाहिए कि हमारे सामने जुड़वां बच्चे हैं। लेकिन हमारा प्रोग्राम और == ऑपरेटर इसके विपरीत बताते हैं। हम इस व्यवहार को कैसे बदल सकते हैं और यह सुनिश्चित कर सकते हैं कि डीएनए मिलान होने पर प्रोग्राम सही परिणाम देता है? इसके लिए जावा के पास एक विशेष तरीका है: बराबर ()ToString () पद्धति की तरह , जिसकी हमने पहले चर्चा की, बराबर () ऑब्जेक्ट क्लास से संबंधित है - जावा में सबसे महत्वपूर्ण वर्ग, वह वर्ग जिससे अन्य सभी वर्ग प्राप्त होते हैं। लेकिन बराबर ()हमारे प्रोग्राम के व्यवहार को अपने आप नहीं बदलता है:

public class Man {

   String geneticCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.geneticCode = "111122223333";

       Man man2 = new Man();
       man2.geneticCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
कंसोल आउटपुट: गलत बिल्कुल वही परिणाम, तो हमें इस विधि की क्या आवश्यकता है? :/ यह सब आसान है। यहाँ मुद्दा यह है कि हम वर्तमान में इस पद्धति का उपयोग कर रहे हैं क्योंकि यह ऑब्जेक्ट क्लास में लागू है। और अगर हम ऑब्जेक्ट क्लास के कोड में जाते हैं और विधि के कार्यान्वयन को देखते हैं, तो हम यही देखेंगे:

public boolean equals(Object obj) {
   return (this == obj);
}
यही कारण है कि कार्यक्रम का व्यवहार नहीं बदला है! वही == ऑपरेटर (जो संदर्भों की तुलना करता है) ऑब्जेक्ट क्लास के बराबर() विधि के अंदर प्रयोग किया जाता है। लेकिन इस पद्धति के साथ युक्ति यह है कि हम इसे ओवरराइड कर सकते हैं। ओवरराइड करने का अर्थ है हमारे मैन क्लास में अपनी खुद की बराबरी () विधि लिखना , उसे वह व्यवहार देना जो हमें चाहिए! वर्तमान में, हम इस तथ्य को पसंद नहीं करते हैं कि man1.equals(man2) अनिवार्य रूप से man1 == man2 के समतुल्य है । यहाँ हम इस स्थिति में क्या करेंगे:

public class Man { 

   int dnaCode; 

   public boolean equals(Man man) { 
       return this.dnaCode ==  man.dnaCode; 

   } 

   public static void main(String[] args) { 

       Man man1 = new Man(); 
       man1.dnaCode = 1111222233; 

       Man man2 = new Man(); 
       man2.dnaCode = 1111222233; 

       System.out.println(man1.equals(man2)); 

   } 
} 
कंसोल आउटपुट: सच अब हमें एक पूरी तरह से अलग परिणाम मिलता है! अपनी खुद की बराबरी () पद्धति लिखकर और मानक एक के बजाय इसका उपयोग करके, हमने सही व्यवहार उत्पन्न किया है: अब यदि दो लोगों के डीएनए समान हैं, तो कार्यक्रम रिपोर्ट करता है कि "डीएनए विश्लेषण ने साबित कर दिया है कि वे जुड़वाँ हैं" और यह सच हो जाता है! अपनी कक्षाओं में बराबरी () पद्धति को ओवरराइड करके , आप आसानी से जो भी वस्तु तुलना तर्क चाहते हैं, बना सकते हैं। वास्तव में, हमने केवल वस्तुओं की तुलना को छुआ है। हमसे आगे, इस विषय पर अभी भी एक बड़ा स्टैंडअलोन पाठ है (यदि आप रुचि रखते हैं तो इसे अभी छोड़ दें)।

जावा में तार की तुलना करना

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

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1 == s2);
   }
}
कंसोल आउटपुट: झूठा लेकिन हमें झूठा क्यों मिला? आखिरकार, तार बिल्कुल वही हैं, शब्द के लिए शब्द:/आप शायद कारण अनुमान लगा सकते हैं: ऐसा इसलिए है क्योंकि == ऑपरेटर संदर्भों की तुलना करता है ! स्पष्ट रूप से, s1 और s2 के मेमोरी में अलग-अलग पते हैं। यदि आपने ऐसा सोचा है, तो चलिए अपने उदाहरण पर फिर से काम करते हैं:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = "CodeGym is the best website for learning Java!";
       System.out.println(s1 == s2);
   }
}
अब हमारे पास फिर से दो संदर्भ हैं, लेकिन परिणाम इसके ठीक विपरीत है: कंसोल आउटपुट: सच असहाय रूप से भ्रमित? आइए जानें कि क्या हो रहा है। == ऑपरेटर वास्तव में स्मृति पतों की तुलना करता है यह हमेशा सच होता है और आपको इसमें संदेह करने की जरूरत नहीं है। इसका मतलब है कि अगर s1 == s2 रिटर्न सही है, तो इन दोनों स्ट्रिंग्स का पता एक ही है। और वाकई ये सच है! स्ट्रिंग्स को स्टोर करने के लिए आपको मेमोरी के एक विशेष क्षेत्र से परिचित कराने का समय है: स्ट्रिंग पूल
बराबर और स्ट्रिंग तुलना - 3
स्ट्रिंग पूल आपके द्वारा अपने प्रोग्राम में बनाए गए सभी स्ट्रिंग मानों को संग्रहीत करने के लिए एक क्षेत्र है। इसे क्यों बनाया गया था? जैसा कि हमने पहले कहा, तार सभी वस्तुओं के एक बड़े प्रतिशत का प्रतिनिधित्व करते हैं। कोई भी बड़ा प्रोग्राम बहुत सारे तार बनाता है। मेमोरी को बचाने के लिए स्ट्रिंग पूल बनाया गया था: स्ट्रिंग्स को वहां रखा जाता है और फिर बाद में बनाए गए स्ट्रिंग्स मेमोरी के उसी क्षेत्र को संदर्भित करते हैं - हर बार अतिरिक्त मेमोरी आवंटित करने की कोई आवश्यकता नहीं होती है। हर बार जब आप स्ट्रिंग = "........" लिखते हैं, तो प्रोग्राम यह जांचता है कि स्ट्रिंग पूल में एक समान स्ट्रिंग है या नहीं। अगर वहाँ है, तो एक नई स्ट्रिंग नहीं बनाई जाएगी। और नया संदर्भ स्ट्रिंग पूल में उसी पते को इंगित करेगा (जहां समान स्ट्रिंग स्थित है)। तो जब हमने लिखा

String s1 = "CodeGym is the best website for learning Java!";
String s2 = "CodeGym is the best website for learning Java!";
s2 s1 के समान स्थान की ओर इशारा करता है । पहला कथन स्ट्रिंग पूल में एक नया स्ट्रिंग बनाता है। दूसरा कथन केवल स्मृति के समान क्षेत्र को s1 के रूप में संदर्भित करता है । आप अन्य 500 समान तार बना सकते हैं और परिणाम नहीं बदलेगा। ज़रा ठहरिये। अगर यह सच है, तो यह उदाहरण पहले काम क्यों नहीं किया?

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1 == s2);
   }
}
मुझे लगता है कि आपके अंतर्ज्ञान ने आपको पहले ही कारण बता दिया है =) आगे पढ़ने से पहले अनुमान लगाने का प्रयास करें। आप देख सकते हैं कि इन दो तारों को अलग-अलग तरीकों से घोषित किया गया है। एक नए ऑपरेटर के साथ, और दूसरा इसके बिना। यहाँ कारण निहित है। जब नया ऑपरेटर ऑब्जेक्ट बनाने के लिए उपयोग किया जाता है, तो यह ऑब्जेक्ट के लिए मेमोरी का एक नया क्षेत्र आवंटित करता है। और नए का उपयोग करके बनाई गई एक स्ट्रिंग स्ट्रिंग पूल में समाप्त नहीं होती है - यह एक अलग वस्तु बन जाती है, भले ही इसका पाठ पूरी तरह से स्ट्रिंग पूल में एक स्ट्रिंग से मेल खाता हो। यानी अगर हम निम्नलिखित कोड लिखते हैं:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = "CodeGym is the best website for learning Java!";
       String s3 = new String("CodeGym is the best website for learning Java!");
   }
}
स्मृति में, ऐसा दिखता है:
बराबर और स्ट्रिंग तुलना - 4
और हर बार जब आप नए का उपयोग करके एक नई वस्तु बनाते हैं , तो मेमोरी का एक नया क्षेत्र आवंटित किया जाता है, भले ही नई स्ट्रिंग के अंदर का पाठ समान हो! ऐसा लगता है कि हमने == ऑपरेटर का पता लगा लिया है। लेकिन हमारे नए परिचित, बराबरी () पद्धति के बारे में क्या?

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1.equals(s2));
   }
}
कंसोल आउटपुट: सच दिलचस्प। हम निश्चित हैं कि s1 और s2 स्मृति में विभिन्न क्षेत्रों की ओर इशारा करते हैं। लेकिन बराबर () विधि अभी भी हमें बताती है कि वे समान हैं। क्यों? याद रखें कि हमने पहले कहा था कि हम चाहते हैं कि वस्तुओं की तुलना करने के लिए बराबर () पद्धति को ओवरराइड किया जा सकता है? उन्होंने स्ट्रिंग वर्ग के साथ बस यही किया है । यह बराबरी को ओवरराइड करता है ()तरीका। और संदर्भों की तुलना करने के बजाय, यह तार में वर्णों के अनुक्रम की तुलना करता है। यदि पाठ समान है, तो इससे कोई फर्क नहीं पड़ता कि वे कैसे बनाए गए थे या वे कहाँ संग्रहीत हैं: चाहे स्ट्रिंग पूल में या स्मृति के एक अलग क्षेत्र में। तुलना का परिणाम सत्य होगा। वैसे, जावा आपको केस-असंवेदनशील स्ट्रिंग तुलना करने देता है। आम तौर पर, यदि किसी एक तार में सभी अपरकेस अक्षर हैं, तो तुलना का परिणाम गलत होगा:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CODEGYM IS THE BEST WEBSITE FOR LEARNING JAVA!");
       System.out.println(s1.equals(s2));
   }
}
कंसोल आउटपुट: झूठा केस-असंवेदनशील तुलना के लिए, स्ट्रिंग क्लास में बराबर इग्नोरकेस () विधि है। आप इसका उपयोग कर सकते हैं यदि आप केवल अक्षरों के मामले के बजाय विशिष्ट वर्णों के अनुक्रम की तुलना करने की परवाह करते हैं। उदाहरण के लिए, दो पतों की तुलना करते समय यह सहायक हो सकता है:

public class Main {

   public static void main(String[] args) {

       String address1 = "2311 Broadway Street, San Francisco";
       String address2 = new String("2311 BROADWAY STREET, SAN FRANCISCO");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
इस मामले में, हम स्पष्ट रूप से एक ही पते के बारे में बात कर रहे हैं, इसलिए यह बराबर इग्नोरकेस () विधि का उपयोग करने के लिए समझ में आता है।

String.intern() विधि

स्ट्रिंग क्लास में एक और मुश्किल तरीका है: intern() ; इंटर्न () विधि सीधे स्ट्रिंग पूल के साथ काम करती है। यदि आप कुछ स्ट्रिंग पर इंटर्न () विधि कहते हैं:
  • यह जांचता है कि स्ट्रिंग पूल में मेल खाने वाली स्ट्रिंग है या नहीं
  • यदि वहाँ है, तो यह पूल में स्ट्रिंग का संदर्भ देता है
  • यदि नहीं, तो यह स्ट्रिंग को स्ट्रिंग पूल में जोड़ता है और इसका संदर्भ देता है।
नए का उपयोग करके प्राप्त स्ट्रिंग संदर्भ पर इंटर्न () विधि का उपयोग करने के बाद , हम स्ट्रिंग पूल से स्ट्रिंग संदर्भ के साथ तुलना करने के लिए == ऑपरेटर का उपयोग कर सकते हैं।

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1 == s2.intern());
   }
}
कंसोल आउटपुट: सच जब हमने पहले इन स्ट्रिंग्स की तुलना बिना इंटर्न () के की थी , तो परिणाम गलत था। अब इंटर्न () विधि जाँचती है कि क्या स्ट्रिंग "CodeGym जावा सीखने के लिए सबसे अच्छी साइट है!" स्ट्रिंग पूल में है। बेशक, यह है: हमने इसे बनाया है

String s1 = "CodeGym is the best website for learning Java!";
हम जाँचते हैं कि क्या s1 और s2.intern() द्वारा दिया गया संदर्भ स्मृति के समान क्षेत्र की ओर इशारा करता है। और निश्चित रूप से, वे करते हैं :) संक्षेप में, इस महत्वपूर्ण नियम को याद रखें और लागू करें: स्ट्रिंग्स की तुलना करने के लिए हमेशा बराबरी () विधि का उपयोग करें! स्ट्रिंग्स की तुलना करते समय, हम लगभग हमेशा संदर्भों, मेमोरी के क्षेत्रों या किसी अन्य चीज़ के बजाय उनके पात्रों की तुलना करना चाहते हैं। बराबर () विधि वही करती है जो आपको चाहिए। आपने जो सीखा है उसे सुदृढ़ करने के लिए, हमारा सुझाव है कि आप हमारे जावा कोर्स से एक वीडियो सबक देखें
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION