Java equals()와 hashCode()에 대해

equals()

Example

class Nesoy {
	private int age;
	private String name;

	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

public static void main(String[] args){
	Nesoy p1 = new Nesoy();
	p1.setAge(27);
	p1.setName("YoungJae");

	Nesoy p2 = new Nesoy();
	p2.setAge(27);
	p2.setName("YoungJae");

	System.out.println(p1.equals(p2)); // false
}

왜(Why) 결과가 false일까요?

No Image

어떻게(How) 값이 동일한지 비교할 수 있을까요?

@Override
public boolean equals(Object obj) {

    if (obj == null) {
        return false;
    }

    if (this.getClass() != obj.getClass()) {
        return false;
    }

    if (this == obj) {
        System.out.println("Object Same");
        return true;
    }

    Nesoy that = (Nesoy) obj;

    if (this.name == null && that.name != null) {
        return false;
    }

    if (this.age == that.age && this.name.equals(that.name)) {
        System.out.println("Object Value Same");
        return true;
    }

    return false;
}

Result

No Image

이런 상황은 어떨까요?

Map<Nesoy, Integer> map = new HashMap<Nesoy, Integer>();
map.put(p1, 1);
map.put(p2, 1);
System.out.println(map.size()); // 2

왜(Why) 크기가 2일까요?

어떻게(How) Key 값이 동일하게 인식할 수 있을까요?

@Override
public int hashCode() {

	final int prime = 31;
	int hashCode = 1;

	hashCode = prime * hashCode + ((name == null) ? 0 : name.hashCode());
	hashCode = prime * hashCode + age;

	return hashCode;
}

Result

No Image

어떻게(How) hashCode()는 결정되는걸까요?

Object의 hashCode()

No Image

String의 hashCode()

No Image

왜(Why) 31인가요?

31은 소수이면서 홀수이기 때문에 선택된 값이다. 만일 그 값이 짝수였고 곱셈 결과가 오버플로되었다면 정보는 사라졌을 것이다. 2로 곱하는 것은 비트를 왼쪽으로 shift하는 것과 같기 때문이다. 소수를 사용하는 이점은 그다지 분명하지 않지만 전통적으로 널리 사용된다. 31의 좋은 점은 곱셈을 시프트와 뺄셈의 조합으로 바꾸면 더 좋은 성능을 낼 수 있다는 것이다(31 * i는 (i « 5) - i 와 같다). 최신 VM은 이런 최적화를 자동으로 실행한다.

정리하며

Reference