item 11 incheol - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
Effective Java 3e ์์ดํ 11์ ์์ฝํ ๋ด์ฉ ์ ๋๋ค.
equals๋ฅผ ์ฌ์ ์ํ ํด๋์ค ๋ชจ๋์์ hashCode๋ ์ฌ์ ์ํด์ผ ํ๋ค.
ํด๋น ํด๋์ค์ ์ธ์คํด์ค๋ฅผ HashMap
์ด๋ HashSet
๊ฐ์ ์ปฌ๋ ์
์ ์์๋ก ์ฌ์ฉํ ๋ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ๊ฒ์ด๋ค.
-
equals
๋น๊ต์ ์ฌ์ฉ๋๋ ์ ๋ณด๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋ค๋ฉด, ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋ ๋์ ๊ทธ ๊ฐ์ฒด์hashCode
๋ฉ์๋๋ ๋ช ๋ฒ์ ํธ์ถํด๋ ์ผ๊ด๋๊ฒ ํญ์ ๊ฐ์ ๊ฐ์ ๋ฐํํด์ผ ํ๋ค. equals๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ค๊ณ ํ๋จํ๋ค๋ฉด, ๋ ๊ฐ์ฒด์ hashCode๋ ๋๊ฐ์ ๊ฐ์ ๋ฐํํด์ผ ํ๋ค.
equals๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๋ค๋ฅด๋ค๊ณ ํ๋จ ํ๋๋ผ๋ ๋ ๊ฐ์ฒด์ hashCode๊ฐ ์๋ก ๋ค๋ฅธ ๊ฐ์ ๋ฐํํ ํ์๋ ์๋ค.
hashCode ์ฌ์ ์๋ฅผ ์๋ชปํ์ ๋ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋๋ ์กฐํญ์ ๋ ๋ฒ์งธ๋ค
์ฆ ๋
ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๋ ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํด์ผ ํ๋ค.
HashMap
์ ํด์์ฝ๋๊ฐ ๋ค๋ฅธ ์ํธ๋ฆฌ๋ผ๋ฆฌ๋ ๋์น์ฑ ๋น๊ต
๋ฅผ ์๋์กฐ์ฐจ ํ์ง ์๋๋ก ์ต์ ํ๋์ด ์์ผ๋ฏ๋ก ๋ณ๋์ ๊ฐ์ฒด๋ฅผ HashMap์ Key๋ก ์ฌ์ฉํ ๊ฒฝ์ฐ ์ํ๋ ๊ฐ์ ๋ฆฌํด ๋ฐ์ง ๋ชปํ ๊ฒ์ด๋ค.
๋๋ฑ์ฑ์ด๋ ๋์ผ์ฑ์ ๋ฌด์์ผ๊น?
๋๋ฑ์ฑ(๋์น์ฑ) : ๋ ๊ฐ์ฒด๊ฐ ๋์ผํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋์ง?
๋์ผ์ฑ : ๋ ๊ฐ์ฒด๊ฐ ๋ฌผ๋ฆฌ์ (์ฃผ์)์ผ๋ก ๊ฐ์์ง?
@Override public int hashCode() { return 42; }
์ด ์ฝ๋๋ ๋์น์ธ ๋ชจ๋ ๊ฐ์ฒด์์ ๋๊ฐ์ ํด์์ฝ๋
๋ฅผ ๋ฐํํ๋ ์ ๋ฒํ๋ค. ํ์ง๋ง ๋์ฐํ๊ฒ๋ ๋ชจ๋ ๊ฐ์ฒด์๊ฒ ๋๊ฐ์ ๊ฐ๋ง ๋ด์ด์ฃผ๋ฏ๋ก ๋ชจ๋ ๊ฐ์ฒด๊ฐ ํด์ํ
์ด๋ธ์ ๋ฒํท ํ๋์ ๋ด๊ฒจ ๋ง์น ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ฒ๋ผ ๋์ํ๋ค.
- ๊ฐ์ฒด์ ๋๋จธ์ง
ํต์ฌ ํ๋
๊ฐ๊ฐ์ ๋ํด ๋ค์ ์์ ์ ์ํํ๋ค. - ํด๋น ํ๋์ ํด์์ฝ๋ c๋ฅผ ๊ณ์ฐํ๋ค.
๊ธฐ๋ณธ ํ์ ํ๋๋ผ๋ฉด Type.hashCode(f)๋ฅผ ์ํํ๋ค.
-
์ฐธ์กฐ ํ์ ํ๋์ผ ๊ฒฝ์ฐ ํ์คํ์ ๋ง๋ค์ด hashCode๋ฅผ ํธ์ถํ๋ค.
ํ๋์ ๊ฐ์ด null์ด๋ฉด 0์ ์ฌ์ฉํ๋ค. - ํ๋๊ฐ ๋ฐฐ์ด์ด๋ผ๋ฉด ํต์ฌ ์์ ๊ฐ๊ฐ์ ๋ณ๋ ํ๋์ฒ๋ผ ๋ค๋ฃฌ๋ค. ๋ชจ๋ ์์๊ฐ ํต์ฌ ์์๋ผ๋ฉด Arrays.hashCode๋ฅผ ์ฌ์ฉํ๋ค.
- ์ด์ ๋จ๊ณ์์ ๊ณ์ฐํ ํด์์ฝ๋ c๋ก result๋ฅผ ๊ฐฑ์ ํ๋ค.
- result = 31 * result + c
- result๋ฅผ ๋ฐํํ๋ค.
@Override public int hashCode() {
int result = Short.hashCode(areaCode);
result = 31 * Short.hashCode(prefix);
result = 31 * Short.hashCode(linenum);
return result;
}
31์ด ํ์
์ด๋ฉด์ ์์(prime)
์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๋ง์ฝ ์ด ์ซ์๊ฐ ์ง์์ด๊ณ ์ค๋ฒํ๋ก์ฐ ๊ฐ ๋ฐ์ํ๋ค๋ฉด ์ ๋ณด๋ฅผ ์๊ฒ ๋๋ค. ์์ ๊ฐ์ ๊ณ์ฐ์์ด ๋ฒ๊ฑฐ๋ก์ธ ์ ์๋ค. ์ด๋ฅผ ๊ฐํธํ๊ฒ ์ ๊ณตํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก Objects
ํด๋์ค์ ์ ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
Objects ํด๋์ค๋ ์์์ ๊ฐ์๋งํผ ๊ฐ์ฒด๋ฅผ ๋ฐ์ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํด์ฃผ๋ ์ ์ ๋ฉ์๋์ธ hash๋ฅผ ์ ๊ณตํ๋ค.
@Overrider public int hashCode() {
return Objects.hash(linenum, prefex, areaCode);
}
์ด ๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ์์์ ์๋ น๋๋ก ๊ตฌํํ ์ฝ๋์ ๋น์ทํ ์์ค์ hashCode ํจ์๋ฅผ ๋จ ํ์ค๋ก ์์ฑํ ์ ์๋ค. ํ์ง๋ง ์์ฝ๊ฒ๋ ์๋๋ ๋ ๋๋ฆฌ๋ค.
์
๋ ฅ ์ธ์๋ฅผ ๋ด๊ธฐ ์ํ ๋ฐฐ์ด์ด ๋ง๋ค์ด์ง๊ณ , ์
๋ ฅ ์ค ๊ธฐ๋ณธ ํ์
์ด ์๋ค๋ฉด ๋ฐ์ฑ
๊ณผ ์ธ๋ฐ์ฑ
๋ ๊ฑฐ์ณ์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ฌ๋ hash ๋ฉ์๋๋ ์ฑ๋ฅ์ ๋ฏผ๊ฐํ์ง ์์ ์ํฉ์์๋ง ์ฌ์ฉํ์
ํด๋์ค๊ฐ ๋ถ๋ณ์ด๊ณ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ๋ ๋น์ฉ์ด ํฌ๋ค๋ฉด, ๋งค๋ฒ ์๋ก ๊ณ์ฐํ๊ธฐ ๋ณด๋ค๋ ์บ์ฑ
ํ๋ ๋ฐฉ์์ ๊ณ ๋ คํด์ผ ํ๋ค.
public final class String {
private int hash; // Default to 0
...
// String ํด๋์ค์์ ์ฌ์ฉํ๋ hashCode method
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
}
hashCode๊ฐ ๋ฐํํ๋ ๊ฐ์ ์์ฑ ๊ท์น์ API ์ฌ์ฉ์์๊ฒ ์์ธํ ๊ณตํํ์ง ๋ง์.
๊ทธ๋์ผ ํด๋ผ์ด์ธํธ๊ฐ ์ด ๊ฐ์ ์์งํ์ง ์๊ฒ ๋๊ณ , ์ถํ์ ๊ณ์ฐ ๋ฐฉ์์ ๋ฐ๊ฟ ์๋ ์๋ค.
equals๋ฅผ ์ฌ์ ์ํ ๋๋ hashCode๋ ๋ฐ๋์ ์ฌ์ ์ํด์ผ ํ๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ ๋๋ก ๋์ํ์ง ์์ ๊ฒ์ด๋ค. ์ฌ์ ์ํ hashCode๋ Object์ API ๋ฌธ์์ ๊ธฐ์ ๋ ์ผ๋ฐ ๊ท์ฝ์ ๋ฐ๋ผ์ผ ํ๋ฉฐ, ์๋ก ๋ค๋ฅธ ์ธ์คํด์ค๋ผ๋ฉด ๋๋๋ก ํด์์ฝ๋๋ ์๋ก ๋ค๋ฅด๊ฒ ๊ตฌํํด์ผ ํ๋ค.
์ด๋ ๊ฒ ๊ตฌํํ๊ธฐ๊ฐ ์ด๋ ต์ง๋ ์์ง๋ง ์กฐ๊ธ ๋ฐ๋ถํ ์ผ์ด๊ธด ํ๋ค. ํ์ง๋ง ๊ฑฑ์ ๋ง์๋ผ AutoValue
ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ์ง equals์ hashCode๋ฅผ ์๋์ผ๋ก ๋ง๋ค์ด์ค๋ค.
- Q1. hashcode ๊ฐ์ 42๋ก ํ๋ฉด ์ ํ๋์ ํค์ ๋ชฐ๋ฆฌ๊ฒ ๋ ๊น? hashcode๊ฐ๊ณผ equals๋ ๋น๊ต ์ํ๋๊ฑธ๊น?
-> 31์ ์์์ด๋ฉด์ ํ์์ด๊ธฐ ๋๋ฌธ์ ์ ํ๋ ๊ฐ์ด๋ค. ๋ง์ผ ๊ทธ ๊ฐ์ด ์ง์์๊ณ ๊ณฑ์ ๊ฒฐ๊ณผ๊ฐ ์ค๋ฒํ๋ก๋์๋ค๋ฉด ์ ๋ณด๋ ์ฌ๋ผ์ก์ ๊ฒ์ด๋ค. 2๋ก ๊ณฑํ๋ ๊ฒ์ ๋นํธ๋ฅผ ์ผ์ชฝ์ผ๋ก shiftํ๋ ๊ฒ๊ณผ ๊ฐ๊ธฐ ๋๋ฌธ์ด๋ค. ์์๋ฅผ ์ฌ์ฉํ๋ ์ด์ ์ ๊ทธ๋ค์ง ๋ถ๋ช ํ์ง ์์ง๋ง ์ ํต์ ์ผ๋ก ๋๋ฆฌ ์ฌ์ฉ๋๋ค. 31์ ์ข์ ์ ์ ๊ณฑ์ ์ ์ํํธ์ ๋บ์ ์ ์กฐํฉ์ผ๋ก ๋ฐ๊พธ๋ฉด ๋ ์ข์ ์ฑ๋ฅ์ ๋ผ ์ ์๋ค๋ ๊ฒ์ด๋ค(31 * i๋ (i ยซ 5) - i ์ ๊ฐ๋ค). ์ต์ VM์ ์ด๋ฐ ์ต์ ํ๋ฅผ ์๋์ผ๋ก ์คํํ๋ค. - Q2. 31์ ์ฌ์ฉํ์ง ์๊ณ ์ง์๋ ๋ค๋ฅธ ์๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ฐ์ํ๋ ์ด์๊ฐ ๋ฌด์์ผ๊น?
- ์์๊ฐ ์๋ ๋ค๋ฅธ ์๋ฅผ ์ฌ์ฉํ๋๊ฑด ์ ๋ณด๋ฅผ ์์คํ ์ ์๋ ์ด์ ๊ฐ ์๋ค.(๊ตฌ์ฒด์ ์ธ ์ ๋ณด ์์ค์ ์ด์ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์)
- ์์ ์ค์ 31์ ์ฌ์ฉํ๋ ์ด์ ๋ ์ํํธ์ ๋บ์ ์ผ๋ก ๋์ฒดํ ์ ์์ด JVM ๋ด๋ถ์ ์ผ๋ก ์ต์ ํํด์ ๊ณ์ฐํ ์ ์๋ค. (31 * i == (i << 5) - i)