equals() hashCode()
from java.util.Hashtable Class
hashCode
method and the equals
method.
from java.lang.Object Class
public int hashCode()Returns a hash code value for the object.
This method is supported for the benefit of hashtables such as those provided
by java.util.Hashtable.
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 hashtables. As much as is reasonably practical, the hashCode method defined by class Object does return
distinct integers for distinct objects. (This is typically implemented by converting the
internal address of the object into an integer, but this implementation technique is not
required by the JavaTM programming language.)
Student.java (Hashtable key object)
public class Student{
private String name;
public Student(String name){
this.name = name;
}
public String getName() {
return name;
}
}
HashtableTest.java (Student 객체를 Hashtable 안에 저장하는 내용)
import java.util.*;
public class HashtableTest {
public static void main(String[] args){
Hashtable<Student,String> ht = new Hashtable<Student,String>();
ht.put(new Student("KIM"), "김진호");
ht.put(new Student("LEE"), "이순심");
ht.put(new Student("PARK"), "박찬희");
ht.put(new Student("HONG"), "홍길동");
String name = ht.get(new Student("KIM"));
System.out.println(name); //null
}
}
테스트 결과
Hashtable<key, value>과 같은 Hashing을 기반으로 하는 Collection API 는 key 오브젝트를 해싱하여 산출되는 숫자를 참조하여 value 오브젝트를 저장하게 된다. 자바 오브젝트들은 모두 hashCode() 메소드를 가지고 있으며 객체의 해싱값(해시코드)을 표현한다. 그런데 위의 경우처럼 저장할 때 와 검색할 때 서로 다른 해시코드가 사용된다면 검색을 할 수 없게 된다. 해시코드가 가리키는 저장소에 객체를 저장했다면 검색할 때도 그 곳에 와야만 저장된 객체를 찾을 수가 있는 것이다. 그러므로 API 설명에 나와 있는 것처럼 Collection API를 사용하면서 key object 로 사용될 클래스는 equals(), hashCode() 를 오버라이드해야만 제대로 작동하는 프로그램을 작성할 수 있는 것이다.
수정된 프로그램
Student.java (Hashtable에 저장될 인스턴스의 클래스)
public class Student{
private String name;
public Student(String name){
this.name = name;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
HashtableTest.java(Hashtable에 Student 객체를 저장 및 검색하는 클래스)
import java.util.*;
public class HashtableTest {
public static void main(String[] args){
Hashtable<Student,String> ht = new Hashtable<Student,String>();
ht.put(new Student("KIM"), "김진호");
ht.put(new Student("LEE"), "이순심");
ht.put(new Student("PARK"), "박찬희");
ht.put(new Student("HONG"), "홍길동");
String name = ht.get(new Student("KIM"));
System.out.println(name); // 김진호
}
}
HashSet 을 사용하면서 hashCode()를 오버라이드하지 않은 경우을 테스트한 코드
import java.util.*;
class HashSet_Hashcode
{
public static void main(String[] args)
{
HashSet<Student> hs = new HashSet<Student>();
// hashCode()를 오버라이드해 주지 않았기 때문에 다음 동일학생을 표현한 객체는 서로 다르게 평가된다
hs.add(new Student("홍길동"));
hs.add(new Student("홍길동"));
System.out.println(hs.size()); // 2
}
}
class Student {
String name;
Student(String name) {
this.name = name;
}
String getName() {
return name;
}
}