package java.lang;
public class Object {
    public boolean equals(Object obj) {
        return (this == obj);
    }
    @IntrinsicCandidate
    public native int hashCode();
}모든 Java 객체의 조상 객체인 Object 클래스에 equals()와 hashCode()가 정의되어 있고, 이를 상속받는다.
Identity vs Equality - equals() 참고
조상 객체 Object의 equals()는 두 객체가 동일한지 확인하는 메서드이지만
Object를 상속받은 자식 클래스들 중 String, Integer 등에서 동등성 비교를 하게 오버라이드하였다.
equals() override 전equals()를 재정의하지 않은 객체를 사용했다. 두 employee 인스턴스는 id가 같아서 동일한 사람으로 처리하고 싶지만 false를 반환한다.
public class EqualsTest {
    public static void main(String[] args) {
        Employee employee1 = new Employee();
        Employee employee2 = new Employee();
 
        employee1.setId(1);
        employee2.setId(1);
 
        System.out.println(employee1.equals(employee2));  //false
    }
}equals() override 후이를 해결하기 위해 Employee 클래스에서 equals()를 오버라이드해준다.
@Getter
@Setter
public class Employee {
    private int id;
    private String name;
    @Override
    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());
    }
}equals() override 후 & hashCode() override 전Object의 hashCode()는 객체 메모리 주소값을 반환하기 때문에 employee1과 employee2는 다른 해시값을 가지고, HashSet에서도 각자 다른 위치에 저장된다.
public class EqualsTest {
    public static void main(String[] args) {
        Employee employee1 = new Employee();
        Employee employee2 = new Employee();
 
        employee1.setId(1);
        employee2.setId(1);
        System.out.println(employee1.equals(employee2));  // true
 
        Set<Employee> employees = new HashSet<Employee>();
        employees.add(employee1);
        employees.add(employee2);
         
        System.out.println(employees);  // 2개 객체 출력
    }
}equals() override 전 & hashCode() override 후같은 아이디를 가지면
@Getter
@Setter
public class Employee {
    private int id;
    private String name;
    @Override
    public boolean equals(Object o) {...}
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + getId();
        return result;
    }
}동일한 객체 = 동일한 메모리 주소 = 동일한 해시코드
⇒equlas()를 오버라이드한다면hashCode()도 오버라이드 되어야 한다.
equals()에 사용된 정보가 수정되지 않았다면, hashCode()는 항상 동일한 정수값을 반환해야 한다.equals()에 의해 두 객체가 동일함을 알게되면, hashCode() 메서드를 호출할 때 두 객체가 반드시 동일한 integer 결과값을 만들도록 해야한다.equals()에 의해 두 객체가 동일하지 않다면, hashCode()가 다른 값을 반환해도 된다. (not required)hashCode()와 equals()를 생성하기 위해서는 같은 attribute를 이용한다.equals()는 일관되어야 한다. 객체가 수정되지 않았다면 항상 결과가 동일해야 한다.a.equlas(b) == true이면 a.hashCode() == b.hashCode() 도 true여야 한다.equals()와 hashCode()는 항상 함께 override 되어야 한다.