JavaRush /Java Blog /Random-KO /Java에서 hashCode() 및 equals() 메소드 작업
Lenchik854
레벨 0
Chernihiv

Java에서 hashCode() 및 equals() 메소드 작업

Random-KO 그룹에 게시되었습니다
이번 포스팅에서는 메소드 hashCode()와 에 대한 이해를 간략하게 설명하겠습니다 equals(). 기본 구현과 이를 올바르게 재정의하는 방법에 대해 이야기하고 싶습니다. 또한 Apache Common 패키지의 도우미 클래스를 사용하여 이러한 메서드를 구현하는 방법에 대해서도 쓸 것입니다. Java에서 hashCode() 및 equals() 메소드 작업 - 1이 게시물의 내용:
  1. 및 . hashCode()_equals()
  2. 기본 동작을 재정의합니다.
  3. Apache Commons Lang을 재정의 hashCode()하고 equals()사용합니다.
  4. 기억해야 할 중요한 것.
  5. ORM 사용 시 특별한 주의.
hashCode()및 메소드는 Java 객체의 상위 클래스인 equals()클래스에 정의되었습니다 . Object따라서 모든 Java 객체는 이러한 메소드로부터 기본 구현을 상속합니다.

hashCode() 및 equals() 사용

이 방법은 hashCode()주어진 객체에 대한 고유한 정수 번호를 얻는 데 사용됩니다. 객체를 해시 테이블(버킷이라고도 함)에 데이터 구조로 저장해야 하는 경우 이 숫자를 사용하여 해당 테이블에서의 위치를 ​​결정합니다. 기본적으로 객체에 대한 메서드는 hashCode()객체가 저장된 메모리 위치의 번호를 반환합니다. equals()이름에서 알 수 있듯이 이 메서드는 단순히 두 개체의 동등성을 확인하는 데 사용됩니다. 이 메서드의 기본 구현은 단순히 두 개체의 참조를 확인하여 동일한지 확인합니다.

기본 동작 재정의

클래스에서 이러한 메서드를 재정의하지 않는 한 모든 것이 잘 작동합니다. 그러나 때로는 애플리케이션이 일부 개체의 기본 동작을 변경해야 하는 경우도 있습니다. 가 있는 예를 들어보겠습니다 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에는 몇 가지 기본 속성과 접근자 메서드가 있습니다. 이제 클래스의 두 개체를 비교해야 하는 간단한 상황을 살펴보겠습니다 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));
    }
}
위에 작성된 메서드가 "false"를 반환할 것이라고 추측하는 데에는 투시력이 필요하지 않습니다. 하지만 이 두 객체가 동일하다면 이것이 실제로 맞는 것일까요? 실시간 애플리케이션에서는 메서드가 true를 반환해야 합니다. 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동등성 확인이 "true"를 반환합니다. 그러나 우리는 모든 것을 다 했습니까? 아직 아님. 수정된 클래스를 또 다른 방법으로 테스트해 보겠습니다.
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)두 개체를 인쇄합니다. 두 개체가 동일하고 Set고유한 개체만 포함된 경우 HashSet내부에는 인스턴스가 하나만 있어야 합니다. 두 객체 모두 클래스의 동일한 인스턴스를 참조합니다 Employee. 우리는 무엇을 놓쳤습니까? 우리는 두 번째 중요한 방법을 놓쳤습니다 hashCode(). Java 문서에 따르면 method 를 재정의하면 equals()method 를 재정의해야 합니다 hashCode(). 그럼 우리 클래스에 다른 메서드를 추가해 보겠습니다 Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
이 메소드를 클래스에 한 번 추가하면 하나의 객체만 인쇄되므로 e1과 e2의 동등성을 확인하면 true로 나타납니다.

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();
    }
 }
반면에 코드 편집기 중 하나를 사용하면 몇 가지 멋진 구조를 불러올 수도 있습니다. 예를 들어, Eclipse IDE에서 class >> source > Geneating hashCode() and equals() ...를 마우스 오른쪽 버튼으로 클릭 하면 매우 멋진 구현이 생성됩니다. Java에서 hashCode() 및 equals() 메소드 작업 - 2기억해야 할 중요한 것.
  1. hashCode()및 및 를 모두 호출하려면 항상 동일한 객체 속성을 사용하십시오 equals(). 우리의 경우에는 employee id.
  2. 메서드는 equals()지속적이어야 합니다(객체가 변경되지 않은 경우 메서드는 동일한 값을 반환해야 함).
  3. 는 언제나 a.equals(b)a.hashCode()동일해야 합니다 b.hashCode().
  4. 한 가지 방법을 재정의하는 경우 두 번째 방법도 재정의해야 합니다.

ORM 사용 시 특별한 주의

ORM(ru.wikipedia.org/wiki/ORM)을 다루는 경우 항상 getter를 사용하고 필드 참조를 사용하지 마십시오 hashCode(). equals()이는 ORM에서 때때로 필드가 지연 로드를 사용하여 로드되고 해당 getter가 호출될 때까지 액세스할 수 없기 때문입니다. 예를 들어, 우리 수업에서는 Employee를 사용합니다 e1.id == e2.id. d 필드가 지연 로딩을 사용하여 로드되는 것은 전적으로 가능합니다 i. 필드 중 하나가 0이거나 null일 수 있으며 잘못된 동작이 발생합니다. 그러나 를 사용하면 e1.getId() == e2.getId()지연 로딩을 사용하여 필드가 로드되었더라도 확신할 수 있습니다. getter를 호출하면 필드가 먼저 채워집니다. 이것이 hashCode()및 메소드에 대해 내가 아는 전부입니다 equals(). 이것이 어딘가에 누군가에게 도움이 되기를 바랍니다. 공부 잘 하시길 바랍니다!! ps. 이번이 처음으로 번역을 시도했습니다. 작가가 말하고자 하는 바에 최대한 가깝게 모든 것을 전달하려고 노력했습니다. 의견이 있으시면 댓글에 적어주세요. 엄격하게 판단하지 마세요 :-))) 원본 기사
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION