๋ณธ ์๋ฃ๋ Effective Java 3/E๋ฅผ ๋ฐํ์ผ๋ก ์์ฑ๋์์ต๋๋ค.
equals
๋ฅผ ์ฌ์ ์ํ ํด๋์ค ๋ชจ๋์์ hashCode
๋ ์ฌ์ ์ํด์ผ ํ๋ค.
์๊ทธ๋ผ HashMap
์ด๋ HashSet
๊ฐ์ ์ปฌ๋ ์
์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
- equals - ๋
ผ๋ฆฌ์ ๋์น์ฑ
- equals๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ค๋ฅธ ๋ ๊ฐ์ฒด (์ฃผ์๊ฐ ๋ค๋ฅธ ๋ ๊ฐ์ฒด)๋ฅผ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์์ ๋ํ๋๊ธฐ์ํด ์ฌ์ฉ๋๋ค.
- hashCode - ๋ฌผ๋ฆฌ์ ๋์น์ฑ
- hashCode๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋์ผํจ์ ๋ณด์ฅํ๊ธฐ์ํด ์ฌ์ฉ๋๋ค.
- ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ค๋ฅธ ๋ ๊ฐ์ฒด๋ฅผ ๋ ผ๋ฆฌ์ ๋์ผํจ์ ๋ณด์ฅํ๊ธฐ ์ํด์ hashCode๋ ๋ ผ๋ฆฌ์ ๋์น์ฑ์ ์งํค๋๋ก ํด์ค์ผํ๋ค.
-
equals
๋น๊ต์ ์ฌ์ฉ๋๋ ์ ๋ณด๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋ค๋ฉด, ๊ทธ ๊ฐ์ฒด์hashCode
๋ฉ์๋๋ ๋ช ๋ฒ์ ํธ์ถํด๋ ์ผ๊ด๋๊ฒ ํญ์ ๊ฐ์ ๊ฐ์ ๋ฐํํด์ผ ํ๋ค. (์ผ๊ด์ฑ) -
equals(Object)
๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ค๊ณ ํ๋จํ๋ค๋ฉด, ๋ ๊ฐ์ฒด์hashCode
๋ ๋๊ฐ์ ๊ฐ์ ๋ฐํํด์ผ ํ๋ค. -
equals(Object)
๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๋ค๋ฅด๋ค๊ณ ํ๋จํ๋๋ผ๋, ๋ ๊ฐ์ฒด์hashCode
๊ฐ ์๋ก ๋ค๋ฅธ ๊ฐ์ ๋ฐํํ ํ์๋ ์๋ค.
hashCode
์ฌ์ ์๋ฅผ ์๋ชปํ์ ๋ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋๋ ์กฐํญ์ ๋๋ฒ์งธ๋ค. ์ฆ, ๋
ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๋ ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํด์ผ ํ๋ค.
equals
๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ค๋ฅธ ๋ ๊ฐ์ฒด (์ฃผ์๊ฐ ๋ค๋ฅธ ๋ ๊ฐ์ฒด)๋ฅผ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ๋ค๊ณ ํ ์ ์๋ค.- ํ์ง๋ง
Object
์hashCode
๋ ์ด ๋์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ํ ๋ค๋ฅด๋ค๊ณ ํ๋จํ๋ค. (๋ฌธ์ ์ )
๋ง์ฝ equals
๋ฅผ ์ฌ์ ์ํ๊ณ , hashCode
๋ฅผ ์ฌ์ ์ํ์ง ์์ ์ํ์์ HashMap์ ๋ฃ์ผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
public class Main {
public static void main(String[] args) {
Map<PhoneNumber, String> phoneBook = new HashMap<>();
phoneBook.put(new PhoneNumber(010, 1111, 1111), "binghe");
String name = phoneBook.get(new PhoneNumber(010, 1111, 1111));
System.out.println(name); // null (binghe๊ฐ ๋์์ผ ์ ์)
}
}
์ ์ฝ๋์์ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๋ฅผ HashMap์ ์ธ์ํ์ง ๋ชปํ๋ค.
๊ทธ ์ด์ ๋ HashMap์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๋์น์ฑ์ ํ์ธํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ง์ฝ ๋ฌผ๋ฆฌ์ ๋์น์ฑ(hashCode()
)๊ฐ ์ผ์นํ์ง ์์ผ๋ฉด, ๋
ผ๋ฆฌ์ ๋์น์ฑ(equals()
)๋ฅผ ํ์ธ์กฐ์ฐจ ํ์ง ์๋๋ค.
์ด๋ ๊ฒ ๋๋ฉด ๋ฌธ์ ๋ ์๋ชปํ๋ฉด ํด์ ํ ์ด๋ธ์ ๋ฒํท ํ๋์ ๋ด๊ฒจ ๋ง์น ์ฐ๊ฒฐ๋ฆฌ์คํธ์ฒ๋ผ ๋์ํ๋ค. O(1)์ด O(n)์ด ๋๋ค.
@Override
public int hashCode() {
int result = Integer.hashCode($์ธ์คํด์ค๋ณ์1);
result = 31 * result + Integer.hashCode($์ธ์คํด์ค๋ณ์2);
result = 31 * result + Integer.hashCode($์ธ์คํด์ค๋ณ์3);
return result;
}
- ํต์ฌ ์ธ์คํด์ค ๋ฉค๋ฒ๋ค์ ๊ฐ๊ฐ ์์ ๊ฐ์ด ๊ณ์ฐํ๊ณ ๊ฐฑ์ ํด์ค๋ค.
equals
๋น๊ต์ ์ฌ์ฉ๋์ง ์์ ํ๋๋ '๋ฐ๋์' ์ ์ธํด์ผ ํ๋ค.- ๊ณฑํ ์ซ์๋ฅผ 31๋ก ์ ํ ์ด์ ๋ 31์ด ํ์์ด๋ฉด์ ์์์ด๊ธฐ ๋๋ฌธ์ด๋ค.
ํด์ ์ถฉ๋์ด ๋์ฑ ์ ์ ๋ฐฉ๋ฒ์ ๊ผญ ์จ์ผ ํ๋ค๋ฉด ๊ตฌ์๋ฐ์ com.google.common.hash.Hashing
์ ์ฐธ๊ณ ํ์.
Object ํด๋์ค๋ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํด์ฃผ๋ ๋ฉ์๋์ธ
hash
๋ฅผ ์ ๊ณตํ์ง๋ง, ์๋๊ฐ ๋๋ฆฌ๋ค. ๊ฐ๋ฅํ ์ 2๊ฐ์ง์ค ํ๋๋ฅผ ์ฌ์ฉํ์.
ํด๋์ค๊ฐ ๋ถ๋ณ์ด๊ณ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ๋ ๋น์ฉ์ด ํฌ๋ค๋ฉด, ๋งค๋ฒ ์๋ก ๊ณ์ฐํ๊ธฐ๋ณด๋ค๋ ์บ์ฑํ๋ ๋ฐฉ์์ ๊ณ ๋ คํด์ผ ํ๋ค.
์ด ํ์ ์ ๊ฐ์ฒด๊ฐ ์ฃผ๋ก ํด์์ ํค๋ก ์ฌ์ฉ๋ ๊ฒ ๊ฐ๋ค๋ฉด ์ธ์คํด์ค๊ฐ ๋ง๋ค์ด์ง ๋ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํด๋ฌ์ผ ํ๋ค.
private int hashCode; // ์๋์ผ๋ก 0์ผ๋ก ์ด๊ธฐํ
@Override
public int hashCode() {
int result = hashCode;
if (result == 0) { // ์ง์ฐ ์ด๊ธฐํ (lazy initialization)
int result = Integer.hashCode($์ธ์คํด์ค๋ณ์1);
result = 31 * result + Integer.hashCode($์ธ์คํด์ค๋ณ์2);
result = 31 * result + Integer.hashCode($์ธ์คํด์ค๋ณ์3);
return result;
}
return result;
}
- ์ฑ๋ฅ์ ๋์ธ๋ต์๊ณ ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ ๋ ํต์ฌ ํ๋๋ฅผ ์๋ตํด์๋ ์๋๋ค.
- ์๋์ผ ๋นจ๋ฆฌ์ง๊ฒ ์ง๋ง, ํด์ ํ์ง์ด ๋๋น ์ ธ ํด์ ํ ์ด๋ธ์ ์ฑ๋ฅ์ ์ฌ๊ฐํ๊ฒ ๋จ์ด๋จ๋ฆด ์ ์๋ค.
hashCode
๊ฐ ๋ฐํํ๋ ๊ฐ์ ์์ฑ ๊ท์น์ API ์ฌ์ฉ์์๊ฒ ์์ธํ ๊ณตํํ์ง ๋ง์.- ๊ทธ๋์ผ ํด๋ผ์ด์ธํธ๊ฐ ์ด ๊ฐ์ ์์งํ์ง ์๊ฒ ๋๊ณ , ์ถํ์ ๊ณ์ฐ ๋ฐฉ์์ ๋ฐ๊ฟ ์๋ ์๋ค.
equals
๋ฅผ ์ฌ์ ์ํ ๋๋hashCode
๋ ๋ฐ๋์ ์ฌ์ ์ํ์.- ์ฌ์ ์๋
hashCode
๋Object
์ ์ผ๋ฐ ๊ท์ฝ์ ๋ฐ๋ผ์ผํ๊ณ , ์๋ก ๋ค๋ฅธ ์ธ์คํด์ค๋ผ๋ฉด ํด์์ฝ๋๋ ์๋ก ๋ค๋ฅด๊ฒ ๊ตฌํํด์ผ ํ๋ค. (๋ฌผ๋ฆฌ์ + ๋ ผ๋ฆฌ์ ์ผ๋ก ๋ชจ๋ ๋ค๋ฅด๋ค๋ฉด) - ์์ดํ
10์
AutoValue
ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉดequals
์hashCode
๋ฅผ ๋ชจ๋ ์๋์ผ๋ก ๋ง๋ค์ด์ค๋ค.