반응형
Java에서 사용자가 정의한 클래스(Class)를 가지고 서로 같은 것인지 비교해야 할 때가 있다.
Java의 모든 클래스는 Object 클래스를 상속하고, Object 클래스가 기본으로 가지고 있는 메쏘드 중에서 equals와 hashCode가 있다.
예를 들어, 학교의 수업관리 시스템에서 학생(Student) 클래스를 사용한다고 가정하고 Student 클래스를 정의하면:
public class Student {
    private int studentId;
    private String name;
    private String major;
   
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }
}


위 클래스를 사용하여 아래와 같이 똑같은 학생을 두 개의 다른 인스턴스(instance)로 만들어 비교해 보면:
public static void main(String[] args){
        Student s1 = new Student();
        s1.setStudentId(20101234);
        s1.setName("Gildong Hong");
        s1.setMajor("Computer Science");

        Student s2 = new Student();
        s2.setStudentId(20101234);
        s2.setName("Gildong Hong");
        s2.setMajor("Computer Science");
       
        System.out.println(s1.equals(s2));    // false
}
실행 결과는 false가 나온다.

위 상황에서 두 학생이 학번이 같고 이름도 같고 전공도 같기 때문에 의미상 똑같은 객체라는 것을 Java가 인식할 수 있게 하기 위한 방법이 equals 메쏘드를 override하는 것이다. Student 클래스에 equals를 override하여 구현하면:
public class Student {
    private int studentId;
    private String name;
    private String major;
   
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }
   
    @Override
    public boolean equals(Object o){
        Student s = (Student) o;
        if(studentId == s.getStudentId()
            && name.equals(s.getName())
            && major.equals(s.getMajor())){
            return true;
        } else {
            return false;
        }
    }
}


이 클래스를 가지고 다시 equals 메쏘드로 위의 s1과 s2를 비교하면 같은 것으로 인식할 수 있다.
하지만 equals만 가지고는 HashMap, HashSet과 같이 key, value의 쌍으로 구성되는 자료구조에서는 제대로 작동하지 않는다. 이 때에는 hashCode 메쏘드를 추가로 override하여 구현하면, Student 클래스의 예와 같이 같은 학번, 이름, 전공을 가진 객체의 경우에는 동일한 key로 간주하도록 할 수 있다.
public class Student {
    private int studentId;
    private String name;
    private String major;
   
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }
   
    @Override
    public boolean equals(Object o){
        Student s = (Student) o;
        if(studentId == s.getStudentId()
            && name.equals(s.getName())
            && major.equals(s.getMajor())){
            return true;
        } else {
            return false;
        }
    }
   
    @Override
    public int hashCode(){
        String s = ""+studentId+name+major;
        return s.hashCode();
    }
}


public static void main(String[] args){
        Student s1 = new Student();
        s1.setStudentId(20101234);
        s1.setName("Gildong Hong");
        s1.setMajor("Computer Science");

        Student s2 = new Student();
        s2.setStudentId(20101234);
        s2.setName("Gildong Hong");
        s2.setMajor("Computer Science");
       
        HashMap<Student, String> advisors = new HashMap<Student, String>();
        advisors.put(s1, "prof. Kim");              // s1 클래스를 key로 사용
        System.out.println(advisors.get(s2));   // s2 클래스를 key로 사용
}

위 예제는 같은 멤버변수 값을 가질 경우 같은 hashCode를 리턴하도록 hashCode를 override함으로써 s2 인스턴스를 가지고 "prof. Kim"을 얻을 수 있다.


반응형
블로그 이미지

Bryan_

,