[TIL 26/02/11](Java) hashCode(), equals() 오버라이딩
2026. 2. 11. 17:31

 

이 주제를 다루게 된 배경 먼저 설명하고 주제에 대해 설명할 예정이다.

 

 

public class Student {
	String studentID;
	String studentName;
	
	public Student(String id, String name) {
		studentID = id;
		studentName = name;
	}
	
	@Override
	public String toString() {
		return studentID + " : " + studentName;	
	}
}

=======================================================================================

public class StudentTest {
	public static void main(String[] args) {
		HashSet<Student> set = new HashSet<Student>();
		
		set.add(new Student("100", "류태우"));
		set.add(new Student("200", "남창우"));
		set.add(new Student("300", "김민성"));
		set.add(new Student("100", "고건혁"));
		
		System.out.println(set);
	}
}

 

이 코드를 실행하게 되면

 

이렇게 studentID가 100인 류태우와 고건혁이 함께 출력되는데

studentID 값을 기준으로 set에 중복 없이 류태우만을 단일 저장을 해야 하는 상황이었다.

 

 

 

그래서 구현하게 된 코드와 출력 결과를 보면

 

public class Student {
	String studentID;
	String studentName;
	
	public Student(String id, String name) {
		studentID = id;
		studentName = name;
	}
	
	@Override
	public String toString() {
		return studentID + " : " + studentName;	
	}
	
	@Override
	public boolean equals(Object obj) {
        if (!(obj instanceof Student)) return false;
        Student student = (Student) obj;
        return Objects.equals(this.studentID, student.studentID);
	}
	
	@Override
	public int hashCode() {
		return Objects.hash(studentID);
	}
}

 

정상적으로 studentID 값이 100인 류태우만 중복 없이 출력된 것을 확인할 수 있다.

 

 

여기서 이제 의문이 생겼는데, hashCode()와 equals() 메서드를 사용한 이유까지는 알겠지만 문법이 너무 생소했다.

그래서 해당 메서드들의 문법에 대해 알아본 뒤, TIL을 작성하려 한다.

 

 

 


 

 

 

 

Set 자료구조에 객체 넣으려고 하면 먼저 기존에 있던 객체와 새로운 객체 비교하게 되는데


1. hashCode() 로 먼저 두 객체의 hash 값을 계산한 뒤

2. 같은 hash 값인지 비교를 한다.

3. hash 값이 같을 경우, equals()로 최종 판정을 하게 된다.

 

위와 같은 과정으로 비교를 하게 된다.

 

 

이것을 이용해 Student 클래스에서 hashCode()와 equals()를 오버라이딩 하여 비교 기준을 studentID로 바꾼 것이다.

 

이제 이 메서드들의 오버라이딩 문법을 살펴볼 것이다.

 

 

 

 


 

 

hashCode()

 

hashCode() 메서드는 객체의 hash 값을 반환하는 메서드이다.

 

기본 구조는

 

public int hashCode()

 

로 반환 타입은 정수형이고 HashSet, HashMap 과 같은 hash 기반 자료구조에서 사용된다.

 

기본적으로는 객체를 식별하기 위한 정수값을 가지고 있기 때문에 서로 다른 객체는 대부분 다른 hash 값을 가지게 되고,

같은 객체로 판단될 가능성이 있는 객체들은 같은 hash 값을 가져야 한다.

 

 

 

 

이제 예제에서 오버라이딩 한 코드를 봐보겠다.

@Override
public int hashCode() {
    return Objects.hash(studentID);
}

 

Objects 클래스의 hash() 메서드로 studentID 를  현재 객체의 hash 값으로 설정했다고 보면 된다.

 

 

 

이제 HashSet의 add 과정에서 hash 값을 비교할 때 두 값이 같은 걸로 판단되기 때문에 equals() 메서드로 최종 판정을 하게 될 것이다.

 

 

 

 

 

equals()

 

equals() 메서드는 두 객체가 논리적으로 같은 객체인지 확인하는 메서드이다.

 

기본 구조는

 

public boolean equals(Object obj)

 

가 되는데, 매개변수가 Object인 이유는 모든 클래스의 최상위 클래스가 Object이기 때문에

어떤 객체든 Object 타입으로 받을 수 있도록 설계되어 있다.

 

기본적으로는 참조 비교(메모리 주소 비교)를 하기 때문에 studentID 값으로 비교를 하기 위해서는 오버라이딩이 필요하다.

 

 

 

이제 예제에서 오버라이딩 한 코드를 보면서 정리를 하겠다.

 

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Student)) return false;
    Student student = (Student) obj;
    return Objects.equals(this.studentID, student.studentID);
}

 

 

1.

 

매개변수의 타입이 Object 이기 때문에 다른 형태의 객체도 비교 대상으로 받을 수 있기 때문에

instanceof 연산자로 현재 내가 비교하고자 하는 객체의 형태가 맞는지 확인하는 절차가 필요하다.

 

 

2.

 

(Student) obj 는 Object 라는 최상위 객체에서 Student 클래스로 다운캐스팅을 하기 위한 문법이다.

 

이로써 equals()의 매개변수로 받은 객체를 Student 타입으로 다룰 수 있게 되고, Student 의 필드인 studentID에 접근할 수 있다.

 

 

3.

 

마지막으로 Objects.equals() 메서드를 이용해 두 studentID 의 값이 같은지를 boolean으로 반환한다.

 

studentID.equals() 로 비교를 하면 null 값이 들어왔을 때 오류가 일어날 수 있기 때문에

더 안전한 방법인 Objects.equals() 메서드를 이용했다.

 

 

equals()로 두 객체가 같다고 판단된다면, 반드시 hashCode()도 같은 값을 반환해야 한다.

  • 먼저 hashCode()로 같은 버킷에 들어갈 수 있는지 판단하고
  • 그 다음 equals()로 최종 비교를 하기 때문

 

 

 

 

후기

 

이번 학습을 통해 HashSet 에서 객체의 중복을 판단하는 과정이

단순히 equals()만 사용하는 것이 아니라 hashCode() → equals() 순서로 동작한다는 것을 이해하게 됐고,

그 과정에서 처음 접하는 문법들도 있어서 많은 정보를 얻은 것 같아 기쁘다.

 

'AIBE5 TIL' 카테고리의 다른 글

[TIL 26/03/04](DB) GROUP BY  (0) 2026.03.04
[TIL 26/02/12](Java) Stream  (0) 2026.02.12
[TIL 26/02/10](Java) 인터페이스  (0) 2026.02.10
[TIL 26/02/09](Java) 상속  (0) 2026.02.09
[TIL 26/02/06](Java) 접근제어자와 캡슐화  (0) 2026.02.06