해시함수(hash function)는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이다.
해시함수에 의해 얻어지는 값은 해시값, 해시코드, 해시체크섬 또는 간단하게 해시라고 한다.
HashSet, HashMap, Hashtable과 같은 객체들을 사용할 경우,
객체가 서로 같은지를 비교하기 위해 equals()메서드와 hashCode()메서드를 호출한다.
그래서 객체가 서로 같은지여부를 결정하려면 두 메서드를 재정의 해야한다.
객체가 같은지 여부는 데이터를 추가할 때 검사한다.
<equals()메서드와 hashCode()메서드에 관련된 규칙>
1. 두 객체가 같으면 반드시 같은 hashCode를 가져야 한다.
2. 두 객체가 같으면 equals()호출했을때 true를 반환해야 한다.
즉, 객체 a, b가 같으면 a.equals(b)와 b.equals(a) 둘다 true이어야 한다.
3. 두 객체의 hashCode가 같다고 해서 두 객체가 반드시 같은 객체는 아니다.
하지만 두 객체가 같으면 반드시 hashCode가 같아야 한다.
4. equals()메서드를 override하면 반드시 hashCode()도 override해야 한다.
5. hashCode()는 기본적으로 Heap메모리에 있는 각 객체에 대한 메모리 주소 매핑정보를
기반으로 한 정수값을 반환한다.그러므로,
클래스에서 hashCode()메서드를 override하지 않으면 절대로 두 객체가 같은 것으로 간주될 수없다.
예제
package kr.or.ddit.basic;
import java.util.HashSet;
import java.util.Set;
public class T07EqualsHashcodeTest {
public static void main(String[] args) {
String str = "홍길동";
System.out.println(str.hashCode());
// str.hashCode()값은 int값인 정수가 나옴 hashCode는 int타입이다.
System.out.println(str.contentEquals(str));
Person p1 = new Person(1, "홍길동");
Person p2 = new Person(1, "홍길동");
Person p3 = new Person(1, "이순신");
// 오브젝트 관점에서는 false 생성됨 p1과 p2는 생성되는 메모리 위치가 달라서
System.out.println("p1.equals(p2) : " + p1.equals(p2));
System.out.println("p1 == p2 : " + (p1 == p2));
// 오브젝트에서 같은 값으로 보려면 p1 == p1으로 해야함
System.out.println("p1 == p1 : " + (p1 == p1));
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
// 이경우 2112로 다른값을 넣었는데 해쉬코드는 같은 값이 나오는 충돌이 발생함
System.out.println("Aa".hashCode());
System.out.println("Bb".hashCode());
Set<Person> set = new HashSet<Person>();
set.add(p1);
set.add(p2);
System.out.println("p1, p2등록 후 데이터 : ");
for (Person p : set) {
System.out.println(p.getId() + " : " + p.getName());
}
System.out.println("add(p3) 성공여부 : " + set.add(p3));
System.out.println("add(p3) 후 데이터 : ");
for (Person p : set) {
System.out.println(p.getId() + " : " + p.getName());
}
System.out.println("remove(p2) 성공여부 : " + set.remove(p2));
System.out.println("remove(p2) 후 데이터 : ");
for (Person p : set) {
System.out.println(p.getId() + " : " + p.getName());
}
}
}
//extends Object 이건 자동생성이라 생략되어있음
class Person {
private int id;
private String name;
public Person(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
}
// @Override
// public int hashCode() {
// return (name + id).hashCode();
// }
// @Override
// public boolean equals(Object obj) {
// Person = p (Person) obj;
// return this.getId() == p.getId() && this.getName().equals(p.getName());
// }
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
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;
Person other = (Person) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
'고급JAVA' 카테고리의 다른 글
Map (0) | 2022.07.23 |
---|---|
Treeset (0) | 2022.07.23 |
Hashset (0) | 2022.07.23 |
Comparable / Comparator (0) | 2022.07.23 |
Stack & Queue (0) | 2022.07.23 |