JavaRush /Java блогы /Random-KK /Java тіліндегі тең мәндер және жолды салыстыру - Жолды са...

Java тіліндегі тең мәндер және жолды салыстыру - Жолды салыстыру

Топта жарияланған
Сәлеметсіз бе! Бүгін біз өте маңызды және қызықты тақырып туралы сөйлесетін боламыз, атап айтқанда Java тілінде an objectілерді бір-бірімен теңестіру() салыстыру. Шынында да, Java-да қандай жағдайларда А нысаны В нысанына тең болады ? Теңдіктер және жолды салыстыру – 1Мысал жазуға тырысайық:
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);
   }
}
Консоль шығысы:

false
Жарайды, тоқта. Неліктен бұл екі көлік тең емес? Біз оларға бірдей қасиеттер бердік, бірақ салыстыру нәтижесі жалған. Жауап қарапайым. Оператор ==an objectілердің қасиеттерін емес, сілтемелерді салыстырады. Екі нысанның 500 бірдей қасиеті болса да, салыстыру нәтижесі жалған болады. Өйткені, сілтемелер екі түрлі нысанға , екі түрлі мекенжайға car1нұсқайды . Адамдарды салыстыру арқылы жағдайды елестетіп көріңіз. Дүниеде аты-жөні, көзінің түсі, жасы, бойы, шашының түсі, т.б өзіңізге ұқсас адам бар шығар. Яғни, сіз көп жағынан ұқсассыз, бірақ бәрібір егіз емессіз, әсіресе бір адам емессіз. Оператор екі нысанды салыстыру үшін пайдаланған кезде шамамен бірдей логиканы қолданады. Бірақ сіздің бағдарламаңызда басқа логика қажет болса ше? Мысалы, сіздің бағдарламаңыз ДНҚ талдауын модельдесе. Ол екі адамның ДНҚ codeын салыстырып, олардың егіз екенін анықтауы керек. car2 Теңдіктер және жолды салыстыру – 2==
public class Man {

   int 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 == man2);
   }
}
Консоль шығысы:

false
Нәтиже бірдей болғаны қисынды (біз ештеңені өзгерткен жоқпыз), бірақ қазір біз оған риза емеспіз! Шынында да, нақты өмірде ДНҚ талдауы егіздердің алдында тұрғанымызға жүз пайыз кепілдік береді. Бірақ біздің бағдарлама мен оператор ==бізге басқаша айтады. Бұл әрекетті қалай өзгерте аламыз және егер ДНҚ сынақтары сәйкес келсе, бағдарлама дұрыс нәтиже беретініне көз жеткізе аламыз? Осы мақсатта Java тілінде арнайы әдіс жасалды - equals() .

Java тіліндегі Equals() әдісі

toString()Біз бұрын талқылаған әдіс сияқты , equals()Object барлық басқа сыныптар алынған Java тіліндегі ең маңызды класс класына жатады . Дегенмен, equals() өзі біздің бағдарламамыздың әрекетін ешбір жолмен өзгертпейді:
public class Man {

   String dnaCode;

   public static void main(String[] args) {

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

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

       System.out.println(man1.equals(man2));
   }
}
Консоль шығысы:

false
Дәл сол нәтиже, сондықтан бұл әдіс не үшін қажет? :/ Бәрі оңай. Өйткені, қазір біз бұл әдісті сыныптың өзінде іске асырғандықтан қолдандық Object. Егер біз сынып codeына кіріп Object, онда бұл әдіс қалай жүзеге асырылатынын және оның не істейтінін қарастырсақ, біз көреміз:
public boolean equals(Object obj) {
   return (this == obj);
}
Біздің бағдарламаның мінез-құлқының өзгермеген себебі де осы! Сыныптың equals() әдісінің ішінде Objectбірдей анықтамалық салыстыру бар ==. Бірақ бұл әдістің айласы - біз оны жоққа шығара аламыз. Алдын ала анықтау дегеніміз - біздің сыныпта өзіңіздің equals() әдісіңізді жазу Manжәне оны біз қалағандай ету! 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));

   }
}
Консоль шығысы:

true
Мүлдем басқа нәтиже! Стандартты әдістің орнына меншікті equals() әдісін жазу арқылы біз дұрыс әрекетке қол жеткіздік: енді екі адамның ДНҚ codeы бірдей болса, бағдарлама бізге: «ДНҚ талдауы олардың егіз екенін көрсетті» деп айтады және шындықты қайтарады! Сыныптарыңыздағы equals() әдісін қайта анықтау арқылы сіз қажетті an object салыстыру логикасын оңай жасай аласыз. Объектілерді салыстыруды біз жалпы түрде ғана қозғадық. Алда бұл тақырып бойынша бөлек үлкен лекциямыз бар (қызық болса, қазір тез оқи аласыз).

Java тіліндегі жолды салыстыру - Жолды салыстыру

Неліктен біз жолды салыстыруды басқалардан бөлек қарастырамыз? Шын мәнінде, бағдарламалаудағы сызықтар - бұл мүлдем басқа тарих. Біріншіден, егер сіз адамзат жазған барлық Java бағдарламаларын алсаңыз, олардағы нысандардың шамамен 25% -ы олардан тұрады. Сондықтан бұл тақырып өте маңызды. Екіншіден, жолдарды салыстыру процесі шын мәнінде басқа нысандардан айтарлықтай ерекшеленеді. Қарапайым мысалды қарастырайық:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Консоль шығысы:

false
Бірақ неге жалған? Жолдар бірдей, сөзбе-сөз :/ Сіз болжауға болады: бұл оператор == сілтемелерді салыстырады! Өйткені, s1олардың s2жадында әртүрлі addressтер бар. Егер сізде бұл ой болса, мысалды қайталайық:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
Енді бізде екі сілтеме бар, бірақ нәтиже керісінше өзгерді: Консоль шығысы:

true
Толығымен шатастырды ма? :) Оны анықтап көрейік. Оператор ==шын мәнінде жадтағы мекенжайларды салыстырады. Бұл ереже әрқашан жұмыс істейді және оған күмәнданудың қажеті жоқ. s1 == s2Бұл шын мәнін қайтарса, бұл екі жолдың жадта бірдей мекенжайы бар екенін білдіреді . Және шынымен де солай! Жолдарды сақтауға арналған арнайы жад аймағымен танысу уақыты келді - жолдық пул ( String pool) Теңдіктер және жолды салыстыру – 3Жолдық пул - бұл сіздің бағдарламаңызда жасайтын барлық жол мәндерін сақтауға арналған аймақ. Ол не үшін құрылды? Жоғарыда айтылғандай, жолдар барлық an objectілердің үлкен бөлігін алады. Кез келген үлкен бағдарламада көптеген жолдар жасалады. Жадты сақтау үшін бұл қажет String Pool- қажетті мәтіні бар жол сол жерде орналастырылады және болашақта жаңадан жасалған сілтемелер бір жад аймағына сілтеме жасайды, әр уақытта қосымша жадты бөлудің қажеті жоқ. Сіз жазған сайын String = “........”бағдарлама жол пулында осындай мәтіні бар жолдың бар-жоғын тексереді. Егер бар болса, жаңасы жасалмайды. Және жаңа сілтеме осы жол сақталған жол пулындағы бірдей мекенжайды көрсетеді. Сондықтан, біз бағдарламада жазған кезде
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush is the best site to learn Java!";
сілтеме s2дәл сол орынды көрсетеді s1. Бірінші пәрмен жол пулында бізге қажетті мәтінмен жаңа жолды жасады, ал екіншісіне келгенде, ол жай ғана сияқты жад аймағына сілтеме жасады s1. Бір мәтінмен кемінде 500 қосымша жол жасауға болады, нәтиже өзгермейді. Тоқта. Бірақ неге бұл мысал бұрын біз үшін жұмыс істемеді?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Менің ойымша, интуитивті түрде сіз оның себебі неде екенін болжайсыз :) Әрі қарай оқымас бұрын болжап көріңіз. Бұл екі жолдың басқаша жасалғанын көруге болады. Біреуі оператордың көмегімен new, екіншісі онсыз. Дәл осы себеп. Жаңа оператор нысанды құру кезінде ол үшін жадта жаңа аумақты мәжбүрлеп бөледі . Ал -мен жасалған жол -мен newаяқталмайды String Pool: оның мәтіні 'a-дан алынған жолдың дәлдігімен бірдей болса да, ол жеке нысанға айналады String Pool. Яғни, келесі codeты жазсақ:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
Жадта ол келесідей болады: Теңдіктер және жолды салыстыру – 4Жаңа нысан жасалған сайын newжадта жаңа аймақ бөлінеді, тіпті жаңа жолдар ішіндегі мәтін бірдей болса да! Біз операторды сұрыптаған сияқтымыз ==, бірақ біздің жаңа досымыз – equals() әдісі туралы не деуге болады?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
Консоль шығысы:

true
Қызықты. Біз нақты нені білеміз s1және s2жадтағы әртүрлі аймақтарды көрсетеміз. Бірақ, соған қарамастан, equals() әдісі олардың тең екенін айтады. Неліктен? Есіңізде болсын, жоғарыда біз теңдік() әдісін сіздің сыныпта қайта анықтауға болады, сонда ол нысандарды сізге қажет жолмен салыстырады? Олар сыныппен осылай істеді String. Оның қайта анықталған equals() әдісі бар. Және ол сілтемелерді емес, жолдардағы таңбалар тізбегін салыстырады. Ал егер жолдардағы мәтін бірдей болса, олардың қалай жасалғаны және қайда сақталғаны маңызды емес: жолдық пулда немесе бөлек жад аймағында. Салыстыру нәтижесі ақиқат болады. Айтпақшы, Java сізге регистрді ескермейтін жолдарды дұрыс салыстыруға мүмкіндік береді. Қалыпты жағдайда, егер сіз жолдардың бірін жазсаңыз, мысалы, бас әріптермен, салыстыру нәтижесі жалған болады:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Консоль шығысы:

false
Бұл жағдайда сыныпта Stringәдіс бар equalsIgnoreCase(). Егер салыстырудағы ең бастысы олардың жағдайы емес, нақты таңбалардың тізбегі болса, оны пайдалануға болады. Мысалы, бұл екі электрондық пошта мекенжайын салыстыру кезінде пайдалы болады:
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
Бұл жағдайда біз бір мекенжай туралы айтып отырғанымыз анық, сондықтан әдісті қолдану equalsIgnoreCase()дұрыс шешім болады.

String.inern() әдісі

Сыныпта Stringтағы бір күрделі әдіс бар - intern(); Әдіс intern()тікелей String Pool'om. intern()Егер сіз жолдағы әдісті шақырсаңыз , ол:
  • Жол пулында осы мәтіні бар жол бар-жоғын көреді
  • Бар болса, оған пулдағы сілтемені қайтарады
  • Олай болмаса, ол осы мәтіні бар жолды жол пулында орналастырады және оған сілтемені қайтарады.
Әдісті intern()new арқылы жасалған жол сілтемесіне қолдану арқылы біз оны String Pool'a арқылы жол сілтемесімен салыстыра аламыз ==.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
Консоль шығысы:

true
Бұрын біз оларды -сыз салыстырған кезде intern(), нәтиже жалған болатын. Енді әдіс «JavaRush – Java тілін үйренуге арналған ең жақсы сайт!»intern() мәтіні бар жолдың бар-жоғын тексерді. жол пулында. Әрине, ол бар: біз оны жазған кезде жасадық
String s1 = "JavaRush is the best site to learn Java!";
s1Сілтеме мен әдіс арқылы қайтарылған сілтеме жадтағы бір аймақты меңзейтіні тексерілді s2.intern(), және, әрине, олар жасайды :) Қорытындылау, есте сақтау және негізгі ережені пайдалану үшін: Жолдарды салыстыру үшін ӘРҚАШАН equals() пайдаланыңыз. әдіс! Жолдарды салыстыру кезінде сіз әрқашан сілтемелерді, жад аймақтарын және т.б. емес, олардың мәтінін салыстыруды білдіреді. equals() әдісі дәл сізге қажет нәрсені жасайды. Өз бетінше оқуға арналған бірнеше сілтемелер:
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION