JavaRush /Java блогу /Random-KY /Java жана String салыштыруу менен барабар - String салышт...

Java жана String салыштыруу менен барабар - String салыштыруу

Группада жарыяланган
Салам! Бүгүн биз абдан маанилүү жана кызыктуу тема жөнүндө сүйлөшөбүз, тактап айтканда Java тorндеги an objectтерди бири-бири менен салыштыруу equals() . Чынында эле, Javaда кандай учурларда А an objectиси В an objectисине барабар болот ? барабар жана сап салыштыруу - 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тердин касиеттерин эмес, шилтемелерди салыштырат. Эки an object 500 окшош касиетке ээ болсо да, салыштыруунун натыйжасы баары бир жалган болот. Анткени, шилтемелер эки башка an objectти , эки башка даректи car1көрсөтөт . Адамдарды салыштыруу менен кырдаалды элестетиңиз. Аты-жөнү, көзүнүн түсү, жашы, бою, чачынын түсү ж.б. окшош адам дүйнөдө бардыр. Башкача айтканда, сиз көп жагынан окшошсуз, бирок баары бир эгиз эмессиз, өзгөчө бир эле адам эмессиз. Оператор эки an objectти салыштыруу үчүн колдонгондо болжол менен бирдей логиканы колдонот. Бирок программаңызда башка логика керек болсочы? Мисалы, сиздин программаңыз ДНК анализин окшоштурса. Ал эки адамдын ДНК 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 тorндеги Equals() ыкмасы

toString()Биз мурда талкуулаган метод сыяктуу , equals() класска таандык, ObjectJavaдагы эң маанилүү класс, андан башка бардык класстар келип чыгат. Бирок, equals() өзү биздин программабыздын жүрүм-турумун эч кандай өзгөртө алbyte:
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ошол эле шилтеме салыштыруу бар ==. Бирок бул ыкманын айласы биз аны жокко чыгара алабыз. Жок кылуу - бул классыбызга өзүңүздүн теңдеш () методуңузду жазып 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
Такыр башка натыйжа! Стандарттуу ыкманын ордуна өзүбүздүн теңдеш () ыкмасын жазуу менен биз туура жүрүм-турумга жетиштик: эми эки адамдын ДНК codeу бирдей болсо, программа бизге: "ДНК анализи алардын эгиз экенин көрсөттү" дейт жана чындыкты кайтарат! Класстарыңыздагы equals() ыкмасын жокко чыгаруу менен, сиз керектүү an objectти салыштыруу логикасын оңой түзө аласыз. Объекттерди салыштырууга жалпы мааниде гана токтолдук. Алдыда бул тема боюнча өзүнчө чоң лекциябыз бар (эгер сизди кызыктырса, азыр тез окуй аласыз).

Java'да саптарды салыштыруу - Стринг салыштыруу

Эмне үчүн биз саптарды салыштырууга башка бардык нерселерден өзүнчө мамиле кылабыз? Чындыгында, программалоодогу саптар такыр башка окуя. Биринчиден, эгер сиз адамзат тарабынан жазылган бардык Java программаларын алсаңыз, алардагы an objectтердин 25%га жакыны алардан турат. Ошондуктан бул тема абдан маанилүү. Экинчиден, саптарды салыштыруу процесси чындап эле башка an objectтерден бир топ айырмаланат. Жөнөкөй мисалды карап көрөлү:
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эсинде ар кандай даректер бар. Эгер бул ой сизге келген болсо, анда келгиле, мисалыбызды кайталайлы:
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, экинчиси ансыз. Бул так себеби болуп саналат. Жаңы оператор an objectти түзүүдө ал үчүн эстутумда жаңы аймакты күч менен бөлүп берет . Ал эми менен түзүлгөн сап new, менен бүтпөйт String Pool: ал өзүнчө an object болуп калат, ал тургай анын тексти '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Жана жаңы an object түзүлгөн сайын, 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() методу алардын бирдей экенин айтат. Неге? Эсиңизде болсун, жогоруда биз теңдеш() ыкмасын классыңызда жокко чыгарууга болот деп айтканбыз, андыктан ал an objectтерди сизге керектүү жол менен салыштырат? Алар класс менен ушундай кылышты 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(); Метод 'om intern()менен түздөн-түз иштейт String Pool. 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