반응형
Java에서 사용자가 정의한 클래스(Class)를 가지고 서로 같은 것인지 비교해야 할 때가 있다.
Java의 모든 클래스는 Object 클래스를 상속하고, Object 클래스가 기본으로 가지고 있는 메쏘드 중에서 equals와 hashCode가 있다.
예를 들어, 학교의 수업관리 시스템에서 학생(Student) 클래스를 사용한다고 가정하고 Student 클래스를 정의하면:
위 클래스를 사용하여 아래와 같이 똑같은 학생을 두 개의 다른 인스턴스(instance)로 만들어 비교해 보면:
위 상황에서 두 학생이 학번이 같고 이름도 같고 전공도 같기 때문에 의미상 똑같은 객체라는 것을 Java가 인식할 수 있게 하기 위한 방법이 equals 메쏘드를 override하는 것이다. Student 클래스에 equals를 override하여 구현하면:
이 클래스를 가지고 다시 equals 메쏘드로 위의 s1과 s2를 비교하면 같은 것으로 인식할 수 있다.
하지만 equals만 가지고는 HashMap, HashSet과 같이 key, value의 쌍으로 구성되는 자료구조에서는 제대로 작동하지 않는다. 이 때에는 hashCode 메쏘드를 추가로 override하여 구현하면, Student 클래스의 예와 같이 같은 학번, 이름, 전공을 가진 객체의 경우에는 동일한 key로 간주하도록 할 수 있다.
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"을 얻을 수 있다.
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;
}
}
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가 나온다. 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
}
위 상황에서 두 학생이 학번이 같고 이름도 같고 전공도 같기 때문에 의미상 똑같은 객체라는 것을 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;
}
}
}
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();
}
}
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"을 얻을 수 있다.
반응형
'Development > Java' 카테고리의 다른 글
코드에서 Exception을 catch하지 못할 때: 상위 예외 클래스에 주의 (1) | 2016.07.31 |
---|---|
적합한 데이터 구조 선택: 요구사항 분석의 영향 (0) | 2016.05.01 |
UDP(Datagram) 소켓에 특정 네트워크 인터페이스로 전송되도록 하기 (0) | 2016.03.23 |
Eclipse에서 만든 jar 파일이 java.lang.UnsupportedClassVersionError와 함께 실행되지 않는 경우 (0) | 2015.10.21 |
Java: Enhanced for loop (향상된 for 루프)로 문자열 초기화 불가능 (0) | 2015.01.09 |