[Java] equals(), hashCode(), toString(), @EqualsAndHashCode(), contains()

호호빵·2025년 1월 17일
0

Java

목록 보기
18/19

Object 클래스


public class Object {
	
    public boolean equals(Object obj) {
        return (this == obj);
    }
    // 두 객체의 같고 다름을 참조변수의 주소값으로 판단
    
    public native int hashCode();
    // 해시함수는 찾고자하는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드를 반환
    
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    // 클래스이름에 16진수의 해시코드

}

public class Arrays {

	public static int hashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }
}

equals()

  • Object 클래스로부터 상속받은 equals 메서드는 결국 두 개의 참조변수가 같은 객체를 참조하고 있는지, 즉 두 참조변수에 저장된 주소값이 같은지를 판단하는 기능만 가능
  • equals 메서드로 value 값을 비교하려면 오바라이딩해야 함

String.equals는 가지고 있는 값이 동일하면 TRUE
String == 연산자는 주소값을 비교

하지만, Object 클래스에서의 equals는 equality is the same as object identity, 즉. 객체 동일성이다.

	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TestObject that = (TestObject) o;
        return id == that.id && Objects.equals(name, that.name);
    }

hashCode()

  • 해시함수는 찾고자하는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드를 반환
  • 해싱 알고리즘에 의해 반환된 정수 값
  • HashMap과 같은 자료 구조에서 사용되는 Hash Table에서의 hashing을 가능하게 하는 것을 목적으로 함
  • equals 비교에 사용되는 정보가 변경되지 않았다면, 어플리케이션이 실행되는 동안 그 객체의 hashCode 메소드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다.(단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다.)
  • equals(Object)가 두 객체를 같다고 판단했다면, hashCode는 똑같은 값을 반환해야 한다.
  • equals(Object)가 두 객체를 다르다고 판단했더라도, hashCode가 서로 다른 값을 반환할 필요는 없다. 단, 다른 객체에 대해서는 다른 값을 반환해야 해시테이블의 성능이 좋아진다.
  • HashCode는 객체의 주소값이 아니라, 내부 요소와 값을 다루며 그 값에 따라 HashCode 값도 바뀜
@Override
public int hashCode() {
    int hash = 7;
    hash = 31 * hash + (int) id;
    hash = 31 * hash + (name == null ? 0 : name.hashCode());
    hash = 31 * hash + (email == null ? 0 : email.hashCode());
    return hash;
}

toString()

  • 인스턴스에 대한 정보를 문자열(String)로 제공할 목적으로 정의한 것
	@Override
    public String toString() {
        return "TestObject{" +
            "id=" + id +
            ", name='" + name + '\'' +
            '}';
    }

@EqualsAndHashCode()

  • 클래스 위에 정의하면, 컴파일 시점에 자동으로 객체의 필드로부터 HashCode와 Equals를 오버라이딩하여 구현해주는 애노테이션
  • 클래스에 있는 모든 필드들에 대한 비교를 수행함
  • 옵션

contains()

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

	public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    /**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index {@code i} such that
     * {@code Objects.equals(o, get(i))},
     * or -1 if there is no such index.
     */
    public int indexOf(Object o) {
        return indexOfRange(o, 0, size);
    }

    int indexOfRange(Object o, int start, int end) {
        Object[] es = elementData;
        if (o == null) {
            for (int i = start; i < end; i++) {
                if (es[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = start; i < end; i++) {
                if (o.equals(es[i])) {
                    return i;
                }
            }
        }
        return -1;
    }
}

containsAll()

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractList() {
    }
    
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }
    
    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }
}

equals()와 hashCode()를 재정의해야하는 경우

경우equals()와 hashCode() 필요 여부비고
HashSet, HashMap, HashTable 사용✅ 필요
contains(), containsKey() 사용✅ 필요
TreeSet, TreeMap 사용✅ 필요 (Comparable과 함께)
객체의 참조 값 비교 (각 객체가 고유해야 함)❌ 불필요
Enum 타입❌ 불필요




reference

https://www.baeldung.com/java-hashcode#standard-hashcode-implementations
https://velog.io/@jyleedev/EqualsAndHashCode-%EA%B7%B8%EB%A6%AC%EA%B3%A0-HashCode%EC%99%80-Equals
https://velog.io/@user1/EqualsAndHashCode-%EC%9D%98-%EC%98%B5%EC%85%98
https://velog.io/@injoon2019/%EC%9E%90%EB%B0%94-equals-hashCode-toString
contains()

profile
하루에 한 개념씩

0개의 댓글

관련 채용 정보