다 필요없고 이클립스 씁시다 오오 이클립스 오오

항목 8 에 대한 글에서 이클립스에서 자동으로 equals 를 만드는 방법을 알려드렸습니다. 거기에 hashCode도 따라서 만들어지는데 그거 쓰면됩니다.
2011/12/09 - [Effective Java] - 항목 8. equals 메소드를 오버라이딩 할때는 보편적 계약을 따르자.
이 항목에서 많은 내용이 적혀있는데 걍 만들어주는거 쓰면 거의 대부분의 내용이 부합한다.

하지만 데이터의 특성에 맞는 해시코드를 만드는 것은 프로그래머가 직접 작성해야할것이다.
hash값을 균등 분포하도록 만드는 해시함수는 직접 만드는수 밖에 없기때문이다.

hashCode 메소드는 여러곳에서 사용되지만 주로 HashMap나 HashSet 에서 사용한다.
hashCode 메소드를 이용해서 해시값을 구하기 때문에 사용할때 주의해야할 점이 있다.
package myproject;

import java.util.HashMap;
import java.util.Map;

public class Test {
	int i;

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + i;
		return result;
	}

	public Test(int i) {
		this.i=i;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Test other = (Test) obj;
		if (i != other.i)
			return false;
		return true;
	}

	
	public static void main(String[] args) {
		Map<Test, Integer> map=new HashMap<Test, Integer>();
		Test t1=new Test(10);
		Test t2=new Test(10);
		map.put(t1, 100);
		System.out.println(map.get(t2));
		System.out.println(map.get(t1));
		t1.i=100;
		System.out.println(map.get(t2));
		System.out.println(map.get(t1));
	}
}


위의 코드를 실행하면 어떤 결과를 출력할까?
100
100
null
null

이런 결과가 나옵니다.
왜 이런 결과가 나올까 하고 생각해볼 필요가 있습니다.
처음에는 Test 클레스의 객체 t1에서 i=10 이라는 값을 이용해서 해시를 합니다.

임의로 i=10 일때 hashCode 값이 10 이라고 합시다.
이때 t1을 이용해서 100이라는 값을 HashMap 에 넣게되면 10이라는 버켓에 key=t1 value=100 이 들어갑니다.
이때 t1의 값을 100으로 변경하면 hash 값이 변경되기 때문에 map.get(t1)으로 값을 꺼내올수가 없게됩니다.

그렇다면 t2는 i=10이고 따라서 hashCode 의 값고 10이 될테니까 get(t2)를 하면 100을 리턴받을수 있을까요?
이것도 안됩니다.
hash 라는것이 균등분포를 시킨다고 하지만 중복이 없을수는 없습니다. 그렇기 때문에 key를 항상 value와 같이 저장하게됩니다. 따라서 hash 값을 이용해서 바구니를 찾은 다음 바구니 안에서 key가 같은게 있는지 찾은다음 value를 리턴한다.

따라서 순서대로 따라가보자면
1. t1(i=10), hash=10 이다.
2. map 의 10번 바구니에 key=t1, value=100 이 들어간다.
3. t1의 i를 100으로 바꾼다. 이때 hash 값이 100으로 바뀐다고 가정한다.
4. t1을 이용해서 map에서 값을 꺼내려고 하면 100번 바구니에는 아무것도 없으므로 null이 나온다.
5. t2(i=10) 을 이용해서 map에서 값을 찾게되면 10번 바구니를 제대로 찾는다.
6. 하지만 t1과 t2는 equals 를 이용해서 비교하면 false를 반환한다.
7. 따라서 null을 리턴한다.

결국 처음에 t1을 이용해서 입력한 값 100은 t1의 i를 10으로 되돌리지 않는 한 다시는 찾을수 없는 값이 된다.

잘 설명이 되었는지 잘 모르겠지만 하여튼 key 로 사용하는 객체는 절대로 건드려서는 안된다
물론 hash 나 equals 에 관련없는것은 큰 문제가 없긴 하다.
Posted by 동적할당
: