JavaRush /Java блогу /Random-KY /Java тилинде hashCode() жана equals() методдору менен ишт...
Lenchik854
Деңгээл
Chernihiv

Java тилинде hashCode() жана equals() методдору менен иштөө

Группада жарыяланган
Бул постто мен ыкмалар hashCode()жана equals(). Мен алардын демейки аткарылышы, ошондой эле аларды кантип туура жокко чыгаруу жөнүндө айткым келет. Мен ошондой эле Apache Common пакетинин жардамчы класстарын колдонуу менен бул ыкмаларды ишке ашыруу жөнүндө жазам. Java тorнде hashCode() жана equals() методдору менен иштөө - 1Бул посттун мазмуну:
  1. колдонуу hashCode()жана equals().
  2. Демейки жүрүм-турумду жокко чыгаруу.
  3. Apache Commons Langди жокко чыгаруу hashCode()жана колдонуу.equals()
  4. Эсте калуу маанилүү нерсе.
  5. ORM колдонууда өзгөчө көңүл буруу.
hashCode()жана методдору java an objectилери үчүн аталык класс болуп саналган equals()класста аныкталган . ObjectДемек, бардык java an objectтери демейки ишке ашырууну ушул ыкмалардан мурастап алышат.

hashCode() жана барабар() колдонуу

Метод hashCode()берилген an object үчүн уникалдуу бүтүн санды алуу үчүн колдонулат. Объект хэш tableсында маалымат структурасы катары сакталышы керек болгондо (чака деп да аталат), бул сан анын ошол tableдагы ордун аныктоо үчүн колдонулат. Демейки боюнча, hashCode()an objectтин ыкмасы an object сакталган эстутумдун номерин кайтарат. Метод equals(), анын аты айтып тургандай, эки an objectтин теңдигин текшерүү үчүн колдонулат. Бул ыкманын демейки ишке ашырылышы жөн гана эки an objectтин шилтемелерин текшерип, алардын эквиваленттүү же жокпу.

Демейки жүрүм-турумду жокко чыгаруу

Сабактарыңызда бул ыкмалардын бирин да жокко чыгарбасаңыз, баары жакшы иштейт. Бирок кээде колдонмолор кээ бир an objectтердин демейки жүрүм-турумун өзгөртүүгө туура келет. Сизде бар болгон мисалды алалы Employee. Мындай класстын мүмкүн болгон минималдуу структурасын жазалы.
public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}
Жогоруда сүрөттөлгөн класстын Employeeкээ бир негизги атрибуттары жана аксессуар ыкмалары бар. Эми класстын эки an objectисин салыштырышыбыз керек болгон жөнөкөй жагдайды карап көрөлү Employee.
public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);
        //Печатает false в консоли
        System.out.println(e1.equals(e2));
    }
}
Жогоруда жазылган ыкма "жалган" болуп чыгаарын божомолдоо үчүн көзү ачыктын кереги жок. Бирок бул эки an object бирдей экендигин эске алганда, бул чындыгында туурабы? реалдуу убакыт колдонмосунда, ыкма чындыкты кайтарышы керек. equals()Туура жүрүм-турумга жетүү үчүн, төмөндө жасалган ыкманы жокко чыгарышыбыз керек :
public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}
Бул ыкманы классыңызга кошуңуз Employeeжана эквиваленттүүлүк текшерүү "чындыкты" кайтарат. Бирок, биз бардыгын жасадыкпы? Азырынча жок. Келгиле, өзгөртүлгөн классыбызды дагы бир жол менен сынап көрөлү.
import java.util.HashSet;
import java.util.Set;

public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);

        //Печатает 'true'
        System.out.println(e1.equals(e2));

        Set employees = new HashSet();
        employees.add(e1);
        employees.add(e2);
        //Печатает два an object
        System.out.println(employees);
    }
}
Буйрук System.out.println(employee)эки an objectти басып чыгарат. Эгерде эки an object тең эквиваленттүү болсо жана Setуникалдуу an objectтер гана камтылган болсо, анда HashSetичинде бир гана инстанция болушу керек, б.а. эки an object тең класстын бир эле инстанцияларына кайрылат Employee. Биз эмнени сагындык? Биз экинчи маанилүү ыкманы өткөрүп жибердик hashCode(). Java documentтеринде айтылгандай, эгер сиз методду жокко чыгарсаңыз equals(), анда сиз методду жокко чыгарышыңыз керек hashCode(). Андыктан классыбызга дагы бир ыкманы кошолу Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
Биз бул ыкманы классыбызга бир жолу коштук жана бир гана an object басып чыгарылат, ошентип, e1 жана e2 эквиваленттүүлүгүн текшерүү чындыкты көрсөттү.

Apache Commons Langди жокко чыгаруу hashCode()жана колдонууequals()

Apache Commons чакыруу ыкмалары hashCode()жана equals(). Төмөндө биз колдонууну көрөбүз:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
 private Integer id;
 private String firstname;
 private String lastName;
 private String department;
public Integer getId() {
    return id;
 }
 public void setId(Integer id) {
    this.id = id;
 }
 public String getFirstname() {
    return firstname;
 }
 public void setFirstname(String firstname) {
    this.firstname = firstname;
 }
 public String getLastName() {
    return lastName;
 }
 public void setLastName(String lastName) {
    this.lastName = lastName;
 }
 public String getDepartment() {
    return department;
 }
 public void setDepartment(String department) {
    this.department = department;
 }
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).
           toHashCode();
 }
@Override
 public boolean equals(Object o) {
    if (o == null)
       return false;
    if (o == this)
       return true;
    if (o.getClass() != getClass())
       return false;
    Employee e = (Employee) o;
       return new EqualsBuilder().
              append(getId(), e.getId()).
              isEquals();
    }
 }
Башка жагынан алганда, эгер сиз code редакторлорунун бирин колдонсоңуз, алар сиз үчүн жакшы структураларды чакыра алышы керек. Мисалы, Eclipse IDEде сиз классты оң баскыч менен чыкылдатсаңыз >> булак > Генерация hashCode() жана equals() ... бул сиз үчүн абдан жакшы ишке ашырууну жаратат. Java тorнде hashCode() жана equals() методдору менен иштөө - 2Эсте калуу маанилүү нерсе.
  1. hashCode()жана жана экөөнү тең чакыруу үчүн ар дайым бир эле an object атрибуттарын колдонуңуз equals(). Биздин учурда, биз колдонгон employee id.
  2. Метод equals()туруктуу болушу керек (эгерде an object өзгөрбөсө, метод ошол эле маанини кайтарышы керек).
  3. Качан a.equals(b), анда a.hashCode()ошол эле болушу керек b.hashCode().
  4. Эгер бир ыкманы жокко чыгарсаңыз, экинчисин жокко чыгарышыңыз керек.

ORM колдонууда өзгөчө көңүл буруу

Эгерде сиз ORM (ru.wikipedia.org/wiki/ORM) менен алектенип жатсаңыз, анда дайыма алуучуларды колдонуңуз жана эч качан талаа шилтемелерин колдонбоңуз hashCode(). equals()Себеби, ORMде маал-маалы менен талаалар жалкоо жүктөм менен жүктөлөт жана алардын алуучулары чакырылмайынча жеткorктүү болбойт. Мисалы, биздин класста Employeeбиз колдонобуз e1.id == e2.id. Бул id талаалары жалкоо жүктөө аркылуу жүктөлүшү толук мүмкүн. Талаалардын бири 0 же нөл болушу мүмкүн жана биз туура эмес жүрүм-турумду алабыз. Бирок, эгер колдонулса e1.getId() == e2.getId(), талаалар жалкоо жүктөө аркылуу жүктөлсө дагы ишенсек болот; алуучунун чакыруусу биринчи талааны толтурат. Бул мен hashCode()жана ыкмалары жөнүндө билем equals(). Бул кимдир бирөөгө жардам берет деп үмүттөнөм. Сиздин изилдөө менен ийгorк коштосун!! ps Бул котормодогу биринчи аракетим. Мен баарын автордун айткысы келгенине мүмкүн болушунча жакын жеткирүүгө аракет кылдым. Эгерде сизде кандайдыр бир комментарийлер болсо, комментарийге жазыңыз. Катуу соттобогула :-))) Оригиналдуу макала
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION