Skip to content

Latest commit

ย 

History

History
140 lines (93 loc) ยท 5.8 KB

item11.md

File metadata and controls

140 lines (93 loc) ยท 5.8 KB

๋ณธ ์ž๋ฃŒ๋Š” Effective Java 3/E๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์•„์ดํ…œ 11. equals๋ฅผ ์žฌ์ •์˜ํ•˜๋ ค๊ฑฐ๋“  hashcode๋„ ์žฌ์ •์˜ํ•˜๋ผ

equals๋ฅผ ์žฌ์ •์˜ํ•œ ํด๋ž˜์Šค ๋ชจ๋‘์—์„œ hashCode๋„ ์žฌ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.

์•ˆ๊ทธ๋Ÿผ HashMap์ด๋‚˜ HashSet ๊ฐ™์€ ์ปฌ๋ ‰์…˜์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋‹ค.

  • equals - ๋…ผ๋ฆฌ์  ๋™์น˜์„ฑ
    • equals๋Š” ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐ์ฒด (์ฃผ์†Œ๊ฐ€ ๋‹ค๋ฅธ ๋‘ ๊ฐ์ฒด)๋ฅผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐ™์Œ์„ ๋‚˜ํƒ€๋‚˜๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
  • hashCode - ๋ฌผ๋ฆฌ์  ๋™์น˜์„ฑ
    • hashCode๋Š” ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋™์ผํ•จ์„ ๋ณด์žฅํ•˜๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
    • ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐ์ฒด๋ฅผ ๋…ผ๋ฆฌ์  ๋™์ผํ•จ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด์„  hashCode๋„ ๋…ผ๋ฆฌ์  ๋™์น˜์„ฑ์„ ์ง€ํ‚ค๋„๋ก ํ•ด์ค˜์•ผํ•œ๋‹ค.


Object๋ช…์„ธ - equals

  1. equals ๋น„๊ต์— ์‚ฌ์šฉ๋˜๋Š” ์ •๋ณด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๊ทธ ๊ฐ์ฒด์˜ hashCode ๋ฉ”์„œ๋“œ๋Š” ๋ช‡ ๋ฒˆ์„ ํ˜ธ์ถœํ•ด๋„ ์ผ๊ด€๋˜๊ฒŒ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค. (์ผ๊ด€์„ฑ)

  2. equals(Object)๊ฐ€ ๋‘ ๊ฐ์ฒด๋ฅผ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ•œ๋‹ค๋ฉด, ๋‘ ๊ฐ์ฒด์˜ hashCode๋Š” ๋˜‘๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.

  3. equals(Object)๊ฐ€ ๋‘ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅด๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๋”๋ผ๋„, ๋‘ ๊ฐ์ฒด์˜ hashCode๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

hashCode ์žฌ์ •์˜๋ฅผ ์ž˜๋ชปํ–ˆ์„ ๋•Œ ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์กฐํ•ญ์€ ๋‘๋ฒˆ์งธ๋‹ค. ์ฆ‰, ๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐ™์€ ๊ฐ์ฒด๋Š” ๊ฐ™์€ ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.

  • equals๋Š” ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐ์ฒด (์ฃผ์†Œ๊ฐ€ ๋‹ค๋ฅธ ๋‘ ๊ฐ์ฒด)๋ฅผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐ™๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•˜์ง€๋งŒ Object์˜ hashCode๋Š” ์ด ๋‘˜์„ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ „ํ˜€ ๋‹ค๋ฅด๋‹ค๊ณ  ํŒ๋‹จํ•œ๋‹ค. (๋ฌธ์ œ์ )

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)์ด ๋œ๋‹ค.


hashCode ์žฌ์ •์˜ ๋ฐฉ๋ฒ•

๋ฐฉ๋ฒ• 1

@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์ด ํ™€์ˆ˜์ด๋ฉด์„œ ์†Œ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋ฐฉ๋ฒ• 2

ํ•ด์‹œ ์ถฉ๋Œ์ด ๋”์šฑ ์ ์€ ๋ฐฉ๋ฒ•์„ ๊ผญ ์จ์•ผ ํ•œ๋‹ค๋ฉด ๊ตฌ์•„๋ฐ”์˜ 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๋ฅผ ๋ชจ๋‘ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.