JavaRush /Java Blog /Random-TL /Paggawa gamit ang hashCode() at equals() na mga pamamaraa...
Lenchik854
Antas
Chernihiv

Paggawa gamit ang hashCode() at equals() na mga pamamaraan sa Java

Nai-publish sa grupo
Sa post na ito ay ilalarawan ko ang aking pag-unawa sa mga pamamaraan hashCode()at equals(). Gusto kong pag-usapan ang kanilang default na pagpapatupad, pati na rin kung paano i-override ang mga ito nang tama. Magsusulat din ako tungkol sa pagpapatupad ng mga pamamaraang ito gamit ang mga klase ng helper ng Apache Common package. Работа с методами hashCode() и equals() в языке Java - 1Mga nilalaman ng post na ito:
  1. Paggamit hashCode()ng at equals().
  2. I-override ang default na gawi.
  3. Ino-override hashCode()at equals()ginagamit ang Apache Commons Lang.
  4. Isang bagay na mahalagang tandaan.
  5. Espesyal na Atensyon Kapag Gumagamit ng ORM.
hashCode()Ang at mga pamamaraan equals()ay tinukoy sa class Object, na siyang parent class para sa java objects. Samakatuwid, ang lahat ng java object ay nagmamana ng default na pagpapatupad mula sa mga pamamaraang ito.

Paggamit ng hashCode() at equals()

Ang pamamaraan hashCode()ay ginagamit upang makakuha ng isang natatanging integer na numero para sa isang ibinigay na bagay. Kapag ang isang bagay ay kailangang maimbak bilang isang istraktura ng data sa isang hash table (tinatawag ding bucket), ang numerong ito ay ginagamit upang matukoy ang lokasyon nito sa talahanayang iyon. Bilang default, ibinabalik ng pamamaraan hashCode()para sa isang bagay ang bilang ng lokasyon ng memorya kung saan nakaimbak ang bagay. Ang pamamaraan equals(), gaya ng ipinahihiwatig ng pangalan nito, ay ginagamit upang suriin lamang ang pagkakapantay-pantay ng dalawang bagay. Ang default na pagpapatupad ng pamamaraang ito ay sinusuri lamang ang mga sanggunian ng dalawang bagay upang makita kung ang mga ito ay katumbas.

Ino-override ang default na gawi

Gumagana nang maayos ang lahat hangga't hindi mo i-override ang alinman sa mga pamamaraang ito sa iyong mga klase. Ngunit kung minsan ang mga application ay kailangang baguhin ang default na pag-uugali ng ilang mga bagay. Kumuha tayo ng isang halimbawa kung saan mayroon kang Employee. Isulat natin ang pinakamababang posibleng istraktura ng naturang klase.
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;
    }
}
Ang klase na inilarawan sa itaas Employeeay may ilang pangunahing katangian at paraan ng accessor. Ngayon tingnan natin ang isang simpleng sitwasyon kung saan kailangan nating paghambingin ang dalawang bagay ng klase 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));
    }
}
Hindi kinakailangan ng isang clairvoyant na hulaan na ang pamamaraan sa itaas ay magbabalik ng "false". Ngunit ito ba ay talagang tama, dahil ang dalawang bagay na ito ay pareho? Sa real time na aplikasyon, ang pamamaraan ay dapat bumalik ng totoo. Upang makamit ang tamang pag-uugali, kailangan nating i-override ang pamamaraan equals(), gaya ng ginawa sa ibaba:
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());
}
Idagdag ang paraang ito sa iyong klase Employeeat ang equivalence check ay magbabalik ng “true”. Gayunpaman, nagawa ba natin ang lahat? Hindi pa. Subukan natin ang aming binagong klase sa isa pang paraan.
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. What же мы упустor? Мы упустor второй важный метод hashCode(). Как сказано в documentации java, если вы переопределяете метод equals(), то вы обязаны переопределить метод hashCode(). Итак, давайте добавим ещё один метод в наш класс Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
Мы добавor один раз этот метод в наш класс, и на печать будет выведен только один an object, и, таким образом, проверка эквивалентности е1 и е2 показала true.

Переопределение hashCode() и equals(), используя Apache Commons Lang

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 кликнуть правой клавишей на class >> sourse > Generating hashCode() and equals() … будет сгенерирована очень хорошая реализация для вас. Работа с методами hashCode() и equals() в языке Java - 2То, что важно помнить.
  1. Всегда используйте те же атрибуты an object для вызова и hashCode() и equals(). Как раз в нашем случае, мы использовали employee id.
  2. Метод equals() должен быть устойчивым (если an object не изменялся, метод должен возвращать то же самое meaning).
  3. Всякий раз, когда a.equals(b), то a.hashCode() должно быть таким же, How b.hashCode().
  4. Если вы переопределor один метод, то обязательно должны переопределить второй.

Особое Внимание При Использовании ORM

Если вы имеете дело с ORM (ru.wikipedia.org/wiki/ORM), то всегда используйте геттеры и никогда не используйте в hashCode() и equals() ссылки на поля. Это потому, что в ORM, время от времени поля загружаются при помощи отложенной загрузки (lazy load) и не доступны, пока не вызваны их геттеры. Например, в нашем классе Employee, мы используем e1.id == e2.id. Вполне возможно, что поля id загружены с помощью отложенной загрузки. Одно из полей может быть равно 0 or null и мы получим некорректное поведение. Но, если используется e1.getId() == e2.getId(), мы можем быть уверены, даже если поля были загружены с помощью отложенной загрузки; вызов геттера первым заполнит поле. Это всё, что я знаю о методах hashCode() и equals(). Надеюсь, что это где-нибудь кому-нибудь поможет. Удачи в учебе!! p.s. Это моя первая попытка перевода. Постаралась передать всё How можно ближе к тому, что хотел сказать автор. Если есть замечания, пожалуйста, напишите в комментариях. Строго не судите :-))) Oригинал статьи
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION