Java/유용한 클래스들

equals() 와 hashCode()

robinjoon98 2021. 8. 5. 11:38

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html

 

Object (Java SE 11 & JDK 11 )

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup. The general contract of fi

docs.oracle.com

객체들간의 비교를 할 때 사용하는 equals 메서드가 어떻게 동작하는지 알아보고자 한다. 이 메서드는 자바의 모든 클래스의 슈퍼클래스인 Object 클래스에 정의되어있다. 따라서, 모든 객체에서 별도의 재정의 필요없이 사용할 수 있다. 래퍼런스에는 이렇게 명시되어있다.

public boolean equals​(Object obj)

Indicates whether some other object is "equal to" this one.

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Parameters:
obj - the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise.

해석하면 다음과같다. (non-null reference value 는 null이 아닌 참조값으로 직역되지만, 참조값이라는 말 대신 객체로 써도 의미가 같으므로 객체라 해석함)

public boolean equals​(Object obj)

다른 객체가, 이 객체와 같은지 나타낸다.

equals 메서드는 null이 아닌 객체에 대해 아래의 등가관계를 구현한다.

  • 재귀적이다. null이 아닌 모든 객체 x에 대해 x.equals(x) 는 항상 true 를 반환한다.
  • 대칭적이다. null이 아닌 모든 객체 x, y에 대해 y.equals(x) 가 true를 반환한다면, x.equlas(y)도 항상 true를 반환한다.
  • 삼단논법이 성립한다.null이 아닌 모든 객체 x, y, z에 대해 x.equals(y) 가 true를 반환하고 y.equals(z) 도 true를 반환한다면,  x.equals(z) 도 true를 반환한다.
  • 일관적이다. null이 아닌 모든 객체 x, y에 대해, 객체 x, y가 변경되지 않는 한 x.equals(y) 의 결과는 몇번 호출되어도 항상 같은 결과를 반환한다.
  • null이 아닌 모든 객체 x에 대해 x.equals(null) 은 항상 false를 반환한다.

Object 클래스의 equals 메서드는 null이 아닌 모든 참조변수 x, y에 대해 x와 y가 동일한 객체를 가리키고있을 때만 true를 반환합니다.
일반적으로 equals 메서드를 하위 클래스에서 재정의 했을 경우, hashCode 메서드도 재정의해야 합니다. 왜냐하면, hashCode 메서드는 같은 객체에 대해 같은 해쉬값을 반환해야 하기 때문입니다.

Parameters:
obj - 비교대상이 되는 객체
Returns:
obj 객체와 이 객체가 같을때 true를 반환하고, 같지 않으면 false를 반환합니다.

래퍼런스에는 equals 메서드를 재정의할 때 지켜야 될 사항과, Object 클래스에 기본적으로 정의되어있는 equals 메서드가 어떻게 구현되어있는지 알려 준다. Object 클래스에 정의 된 equals 메서드는 결국 아래 코드이다.

public boolean equals (Object obj){
	if(this == obj) return true;
	else return false;
}

다만, 모든 객체에대해 위와같은 결과를 제공하면, 이 메서드 자체가 의미가 없다. 따라서, 일부 클래스에서 이를 재정의하여 사용하고있다. 대표적으로 String 클래스에선 equals 메서드를 재정의해 내부적인 문자열이 같으면 true를 반환하게끔 되어있다.

중요한 부분은 하나 더 있다. 바로, eauals 메서드를 재정의하였다면 hashCode를 재정의해야된다는 것이다.이를 이해하기 위해 래퍼런스에 있는 hashCode 메서드에 대한 설명을 보자.

public int hashCode()

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (The hashCode may or may not be implemented as some function of an object's memory address at some point in time.)

Returns:
a hash code value for this object.

해석하면 다음과 같다.

public int hashCode()

객체의 해쉬값을 반환한다. 이 메서드는 HashMap 과같은 해쉬테이블을 지원하기 위해 제공됩니다.

hashCode가 재정의 될 시 아래의 규칙을 만족하게 재정의되어야 한다.

  • 자바 어플리케이션이 실행되는동안 이 메서드가 반환하는 정수는 항상 일정해야 합니다. 단, 객체가 변경된경우 변경되기 전에 반환한 정수와 변경된 후 반환한 정수가 다를 수 있습니다. 이 정수는, 여러번의 어플리케이션 실행에서 항상 같을 필요는 없습니다. 
  • 만약, 두 객체에 대해 equals 메서드에 의해 같다고 판단될 경우(equals 메서드가 true를 반환할 경우), 두 객체 각각에서 호출된 hashCode 메서드는 같은 정수를 반환해야 합니다.
  • equals 메서드에 의해 두 객체가 다르다고 판단될 경우에 두 객체에서 각각 호출된 hashCode 메서드가 반환하는 정수가 다를 필요는 없습니다. 단, 프로그래머는 서로 다른 객체에 대해 고유한 정수를 반환하도록 hashCode 메서드가 동작할수록 HashMap 과같은 해쉬테이블의 성능이 향상되므로 최대한 hashCode 메서드가 반환하는 정수가 고유하게끔 코드를 작성해야 합니다.

Object 클래스에 정의된 hashCode 메서드는 충분히 합리적이고 실용적인 수준으로 서로 다른 객체에 대해 고유한 해쉬값을 반환합니다. 

Returns:
이 객체에 대한 해쉬값을 반환합니다.

hashCode 메서드는 HashMap 등의 해쉬테이블을 지원하기 위해 있는 메서드이다. 따라서, 만약 앞으로 영원히 해쉬테이블을 이용해 자신이 작성한 클래스의 객체들을 관리할 일이 없다면, equals 메서드를 재정의하였다고 해서 hashCode 메서드를 재정의 하지 않아도 된다. 그러나, 대부분의 경우 이를 확신할 수 없으니 equals 메서드를 재정의 하였다면 hashCode 메서드도 재정의해야 한다. 

'Java > 유용한 클래스들' 카테고리의 다른 글

String 클래스  (0) 2020.04.27