2023. 1. 30. 11:08ใJAVA/Effective JAVA
item11. equals๋ฅผ ์ฌ์ ์ํ๋ ค๊ฑฐ๋ hashcode๋ ์ฌ์ ์ํ๋ผ.
[์ดํํฐ๋ธ ์๋ฐ] Item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. (equals ๊ตฌํ ๋ฐฉ๋ฒ๊ณผ ์ฃผ์์ฌํญ)
item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. [์ดํํฐ๋ธ ์๋ฐ] Item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. (๋์นญ์ฑ, ๋ฐ์ฌ์ฑ, ์ถ์ด์ฑ) (tistory.com) [์ดํํฐ๋ธ ์๋ฐ] Item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ
hyejin.tistory.com
equals๋ฅผ ์ฌ์ ์ํ ๋ hashcode๋ ๋ฐ๋์ ์ฌ์ ์ ํด์ผ ํ๋ค๊ณ ์ฃผ์์ฌํญ์ผ๋ก ์์ฑํด๋๋ค.
equals๋ฅผ ์ฌ์ ์ํ ํด๋์ค ๋ชจ๋์์ hashcode๋ ์ฌ์ ์ํด์ผํ๋๋ฐ ๊ทธ๋ ์ง ์์ผ๋ฉด hashcode ์ผ๋ฐ ๊ท์ฝ์ ์ด๊ธฐ๊ฒ ๋์ด์ ํด๋น ํด๋์ค์ ์ธ์คํด์ค๋ฅผ HashMap์ด๋ HashSet ๊ฐ์ ์ปฌ๋ ์ ์ ์์๋ก ์ฌ์ฉํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
hashCode ๊ท์ฝ
1๏ธโฃ equals ๋น๊ต์ ์ฌ์ฉํ๋ ์ ๋ณด๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋ค๋ฉด hashCode๋ ๋งค๋ฒ ๊ฐ์ ๊ฐ์ ๋ฆฌํดํด์ผ ํ๋ค.
(๋ณ๊ฒฝ๋๊ฑฐ๋, ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ ์คํํ๋ค๋ฉด ๋ฌ๋ผ์ง ์ ์๋ค.)
2๏ธโฃ ๋ ๊ฐ์ฒด์ ๋ํ equals๊ฐ ๊ฐ๋ค๋ฉด, hashCode์ ๊ฐ๋ ๊ฐ์์ผ ํ๋ค.
3๏ธโฃ ๋ ๊ฐ์ฒด์ ๋ํ equals๊ฐ ๋ค๋ฅด๋๋ผ๋, hashCode์ ๊ฐ์ ๊ฐ์ ์ ์์ง๋ง ํด์ ํ ์ด๋ธ ์ฑ๋ฅ์ ๊ณ ๋ คํด ๋ค๋ฅธ ๊ฐ์ ๋ฆฌํดํ๋ ๊ฒ์ด ์ข๋ค.
-> ์ฌ๊ธฐ์ hashcode ์ฌ์ ์๋ฅผ ์๋ชปํ์ ๋ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋๋ ๊ณณ์ 2๋ฒ์งธ๋ก ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๋ ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํด์ผ ํ๋ค.
public class PhoneNumber
{
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum)
{
this.areaCode = rangeCheck(areaCode, 999, "area code");
this.prefix = rangeCheck(prefix, 999, "prefix");
this.lineNum = rangeCheck(lineNum, 9999, "line num");
}
private static short rangeCheck(int val, int max, String arg)
{
if (val < 0 || val > max) {
throw new IllegalArgumentException(arg + ": " + val);
}
return (short) val;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof PhoneNumber)) {
return false;
}
PhoneNumber that = (PhoneNumber) o;
return areaCode == that.areaCode && prefix == that.prefix && lineNum == that.lineNum;
}
}
์ด๋ ๊ฒ ๋ง์ฝ equals๋ ์ฌ์ ์ ํ๋๋ฐ hashcode๋ ์ฌ์ ์ํ์ง ์์๋๋ผ๋ฉด
public static void main(String[] args)
{
Map<PhoneNumber, String> map = new WeakHashMap<>();
PhoneNumber number1 = new PhoneNumber(123, 456, 7890);
PhoneNumber number2 = new PhoneNumber(123, 456, 7890);
// ๊ฐ์ ์ธ์คํด์ค์ธ๋ฐ ๋ค๋ฅธ hashcode
System.out.println("number1.equals(number2) = " + number1.equals(number2));
System.out.println("number1.hashCode() = " + number1.hashCode());
System.out.println("number2.hashCode() = " + number2.hashCode());
map.put(number1, "hyejin");
map.put(number2, "user");
String s = map.get(number2);
System.out.println("s = " + s);
String s1 = map.get(new PhoneNumber(123, 456, 7890));
System.out.println("s1 = " + s1); // ์๋ฌด๊ฒ๋ ์๋์ด
}
number1๊ณผ number2 ๋ฅผ map์ ๋ฃ๊ณ map.get(number2)๋ฅผ ํ ๋๋ user์ ์ ๋ฐํํ์ง๋ง
๋ฐ์ new PhoneNumber(123, 456, 7890)์ getํ๋ฉด null์ด ๋ฐํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์๋ํ๋ฉด hashcode๋ฅผ ๊ฐ์ด ์ฌ์ ์ํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ ผ๋ฆฌ์ ๋์น์ธ ๋ ๊ฐ์ฒด๊ฐ ์๋ก ๋ค๋ฅธ ํด์์ฝ๋๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ผ์ get ๋ฉ์๋๊ฐ ํด์ ์ฝ๋๊ฐ์ด ๋ฌ๋ผ์ ๋ค๋ฅธ ๊ณณ์ ์ฐพ์ ํค๋งค๊ณ ์๊ธฐ ๋๋ฌธ์ null์ ๋ฐํํ๋ ๊ฒ์ด๋ค.
๐ HashMap์ ํด์์ฝ๋๊ฐ ๋ค๋ฅธ ์ํธ๋ฆฌ๋ผ๋ฆฌ๋ ๋์น์ฑ ๋น๊ต ์๋์กฐ์ฐจ ํ์ง ์๋๋ก ์ต์ ํ ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ hashcode๋ฅผ ์ฌ์ ์ํด์ผํ๋๋ฐ ๋ง์ฝ hashcode ๊ฐ์ ๋ชจ๋ ๋์ผํ๊ฒ ์์ฑํ๋ค๋ฉด ?
@Override
public int hashCode()
{
return 42;
}
์ด ์ฝ๋๋ ๋์น์ธ ๋ชจ๋ ๊ฐ์ฒด์์ ๋๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํ๋ฏ๋ก ์ ๋ฒํ์ง๋ง ๋ชจ๋ ๊ฐ์ฒด์๊ฒ ๋๊ฐ์ ๊ฐ์ ๋ด์ด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๊ฐ์ฒด๊ฐ ํด์ ํ ์ด๋ธ์ ๋ฒํท ํ๋์ ๋ด๊ฒจ ๋ง์น ์ฐ๊ฑธ ๋ฆฌ์คํธ LinkedList์ฒ๋ผ ๋์ํ๋ค.
-> ์ด๋ ๊ฒ ๋๋ฉด ํ๊ท ์ํ ์๊ฐ์ด O(1) ์ธ ํด์ํ ์ด๋ธ์ด O(n) ์ผ๋ก ๋๋ ค์ ธ์, ๊ฐ์ฒด๊ฐ ๋ง์์ง๋ฉด ๋์ ํ ์ธ ์ ์๊ฒ ๋๋ค.
๐ ์ธ๋ฒ์งธ ๊ท์ฝ์์ ๋ ๊ฐ์ฒด์ ๋ํ equals๊ฐ ๋ค๋ฅด๋๋ผ๋, hashCode์ ๊ฐ์ ๊ฐ์ ์ ์๋ค๊ณ ๋ ํ์ง๋ง ์ฑ๋ฅ์ ๋ค๋ฅธ ๊ฐ์ ๋ฆฌํดํ๋๊ฒ ์ข๋ค๊ณ ํ๋ค. ์ข์ ํด์ ํจ์๋ผ๋ฉด ์๋ก ๋ค๋ฅธ ์ธ์คํด์ค์ ๋ค๋ฅธ ํด์์ฝ๋๋ฅผ ๋ฐํํ๋ค.