item 11 hyowon - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
equals๋ฅผ ์ฌ์ ์ํ ํด๋์ค ๋ชจ๋์์ hashCode๋ ์ฌ์ ์ํด์ผ ํ๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด hashCode ์ผ๋ฐ ๊ท์ฝ์ ์ด๊ธฐ๊ฒ ๋์ด HashMap, HashSet ๊ฐ์ ์ปฌ๋ ์ ์ ์์๋ก ์ฌ์ฉํ ๋ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ๊ฒ์ด๋ค.
Object.hashCode()
)
Object ๋ช
์ธ์ ๊ท์ฝ (- equals ๋น๊ต์ ์ฌ์ฉ๋๋ ์ ๋ณด๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋ค๋ฉด, ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋ ๋์ ๊ทธ ๊ฐ์ฒด์ hashCode ๋ฉ์๋๋ ํญ์ ๊ฐ์ ๊ฐ์ ๋ฐํํด์ผ ํ๋ค. ๋จ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์คํํ๋ค๋ฉด ์ด ๊ฐ์ด ๋ฌ๋ผ์ ธ๋ ๋๋ค.
- equals(Object)๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ค๊ณ ํ๋จํ๋ค๋ฉด, ๋ ๊ฐ์ฒด์ hashCode ๋ฐํ๊ฐ์ ๊ฐ์์ผ ํ๋ค.
- equals(Object)๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๋ค๋ฅด๋ค๊ณ ํ๋จํด๋, ๋ ๊ฐ์ฒด์ hashCode ๋ฐํ๊ฐ์ด ๋ค๋ฅผ ํ์๋ ์๋ค.
hashCode ์ฌ์ ์๋ฅผ ์๋ชปํ์ ๋ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋๋ ์กฐํญ์ ๋ ๋ฒ์งธ๋ก, ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๋ ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํด์ผ ํ๋ค. ํ์์ ๋ฐ๋ผ equals๋ ๋ฌผ๋ฆฌ์ (๋์ผ์ฑ)์ผ๋ก ๋ค๋ฅด์ง๋ง ๋ ผ๋ฆฌ์ (๋๋ฑ์ฑ)์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ค๊ณ ์ฌ์ ์ํ ์ ์๋ค.
ํ์ง๋ง Object์ ๊ธฐ๋ณธ hashCode ๋ฉ์๋๋ ์ด ๋์ด ์ ํ ๋ค๋ฅด๋ค๊ณ ํ๋จํ์ฌ, ๊ท์ฝ๊ณผ ๋ฌ๋ฆฌ ๋ค๋ฅธ ๊ฐ์ ๋ฐํํ๋ค.
Map<PhoneNumber, String> m = new HashMap<>();
m.put(new PhoneNumber(031,707,1234), "์ ๋");
m.get(new PhoneNumber(031,707,1234)); // null
์ข์ hashCode๋ฅผ ์์ฑํ๋ ์๋ น
- int ๋ณ์ result๋ฅผ ์ ์ธํ ํ ๊ฐ c๋ก ์ด๊ธฐํ. (์ด ๋ c๋ ํด๋น ๊ฐ์ฒด์ ํต์ฌ ํ๋๋ฅผ 2.1 ๋ฐฉ์์ผ๋ก ๊ณ์ฐํ hashCode์ด๋ค)
- ํด๋น ๊ฐ์ฒด์ ๋๋จธ์ง ํต์ฌ ํ๋ f ๊ฐ๊ฐ์ ๋ํด ๋ค์ ์์
์ ์ํํ๋ค.
-
ํด๋น ํ๋์ ํด์์ฝ๋ c๋ฅผ ๊ณ์ฐํ๋ค.
- (๊ธฐ๋ณธํ์ ์ธ ๊ฒฝ์ฐ) ${Type}.hashCode(f) ๋ฅผ ์ํํ๋ค. Type์ ํด๋น ๊ธฐ๋ณธ ํ์ ์ ๋ฐ์ฑ ํด๋์ค์ด๋ค
- (์ฐธ์กฐํ์ ์ธ ๊ฒฝ์ฐ) ์ด ํด๋์ค์ equals ๋ฉ์๋๊ฐ ์ด ํ๋์ equals๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํด ๋น๊ตํ๋ค๋ฉด ๊ทธ๋ ๊ฒ ํ๋ค. ๋จ, ๊ณ์ฐ์ด ๋ณต์กํ๋ค๋ฉด ์ด ํ๋์ ํ์คํ(canonical representation)์ ๋ง๋ค์ด ๊ทธ ํ์คํ์ hashCode๋ฅผ ํธ์ถํ๋ค. ํ๋์ ๊ฐ์ด null์ด๋ฉด 0์ ์ฌ์ฉํ๋ค.
- (๋ฐฐ์ด์ธ ๊ฒฝ์ฐ) ํต์ฌ ์์ ๊ฐ๊ฐ์ ๋ณ๋ ํ๋์ฒ๋ผ ๋ค๋ฃฌ๋ค. ๋ฐฐ์ด์ ํต์ฌ ์์๊ฐ ํ๋๋ ์๋ค๋ฉด ์์ 0์ ์ฌ์ฉํ๊ณ , ๋ชจ๋ ์์๊ฐ ํต์ฌ ์์๋ผ๋ฉด Arrays.hashCode๋ฅผ ์ฌ์ฉํ๋ค.
-
๋จ๊ณ 2.1์์ ๊ณ์ฐํ ํด์์ฝ๋ c๋ก result๋ฅผ ๊ฐฑ์ ํ๋ค.
result = 31 * result + c;
-
result๋ฅผ ๋ฐํํ๋ค.
-
class PhoneNumber {
private int areaCode;
private String exchangeNumber;
private int[] number;
PhoneNumber(int areaCode, String exchangeNumber, int[] number) {
this.areaCode = areaCode;
this.exchangeNumber = exchangeNumber;
this.number = number;
}
@Override
public int hashCode() {
int result = Objects.hash(areaCode, exchangeNumber);
result = 31 * result + Arrays.hashCode(number);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PhoneNumber that = (PhoneNumber) o;
return areaCode == that.areaCode &&
Objects.equals(exchangeNumber, that.exchangeNumber) &&
Arrays.equals(number, that.number);
}
}
public class ItemEleven {
public static void main(String[] args) {
Map<PhoneNumber, String> m = new HashMap<>();
PhoneNumber pn = new PhoneNumber(031,707,1234);
m.put(pn, "์ ๋");
m.get(new PhoneNumber(031,707,1234));
// hashcode test
System.out.println(m.get(new PhoneNumber(031,707,1234))); // ์ ๋
System.out.println(m.get(pn)); // ์ ๋
System.out.println(new PhoneNumber(031,707,1234).hashCode()); // 1247369920
System.out.println(new PhoneNumber(031,707,1234).hashCode()); // 1247369920
}
}
-
ํด์ ์ถฉ๋์ด ๋์ฑ ์ ์ ๋ฐฉ๋ฒ์ ์ํ๋ค๋ฉด ๊ตฌ์๋ฐ์ com.google.common.hash.Hashing์ ์ฐธ๊ณ ํ์.
-
Object ํด๋์ค๋ ์์ ๊ฐ์์ ๊ฐ์ฒด๋ฅผ ๋ฐ์ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ๋ hash ๋งค์๋๋ฅผ ์ ๊ณตํ๋ค. ๋จ, ์๋๋ ๋๋ ค์ง๋๋ฐ ์ ๋ ฅ ์ธ์๋ฅผ ๋ด๊ธฐ ์ํ ๋ฐฐ์ด์ด ๋ง๋ค์ด์ง๊ณ , ์ ๋ ฅ ์ค ๊ธฐ๋ณธ ํ์ ์ด ์๋ค๋ฉด ๋ฐ์ฑ, ์ธ๋ฐ์ฑ์ด ์ด๋ค์ง๊ธฐ ๋๋ฌธ์ด๋ค.
-
ํด๋์ค๊ฐ ๋ถ๋ณ์ด๊ณ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ๋ ๋น์ฉ์ด ํฌ๋ค๋ฉด, ์บ์ฑํ๋ ๋ฐฉ์์ ๊ณ ๋ คํ์
- ์ด ํ์ ์ ๊ฐ์ฒด๊ฐ ์ฃผ๋ก ํด์์ ํค๋ก ์ฌ์ฉ๋ ๊ฒ ๊ฐ๋ค๋ฉด โ ์ธ์คํด์ค ์์ฑ์ ํด์์ฝ๋๋ฅผ ๊ณ์ฐ
- ์ ์ฌ์ฉ๋์ง ์์ ๊ฒ ๊ฐ๋ค๋ฉด โ ์ง์ฐ ์ด๊ธฐํ ์ ๋ต
// ์ง์ฐ ์ด๊ธฐํ ์ ๋ต private int hashCode; // ์๋์ผ๋ก 0์ผ๋ก ์ด๊ธฐํ @Override public int hashCode() { int result = hashCode; if (result == 0) { result = Integer.hashCode(areaCode); result = 31 * result + exchangeNumber.hashCode(); result = 31 * result + Arrays.hashCode(); hashCode = result; } return result; }
-
์ฑ๋ฅ์ ๋์ธ๋ค๊ณ ํต์ฌ ํ๋๋ฅผ ์๋ตํ๋ค๋ฉด ํด์ ํ์ง์ด ๋๋น ์ ธ ๊ฐ์ ๊ฐ์ด ๋๋์ผ๋ก ์์ฑ๋ ์ ์๋ค.
-
hash ์์ฑ๊ท์น์ api ์ฌ์ฉ์์๊ฒ ๊ณต๊ฐํ์ง ๋ง์. ๊ทธ๋์ผ ํด๋ผ์ด์ธํธ๊ฐ ์ด ๊ฐ์ ์์งํ์ง ์๊ณ ์ถํ ๊ณ์ฐ ๋ฐฉ์์ ๋ฐ๊ฟ ์ ์๋ค.