item 11 incheol - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

Effective Java 3e ์•„์ดํ…œ 11์„ ์š”์•ฝํ•œ ๋‚ด์šฉ ์ž…๋‹ˆ๋‹ค.

equals๋ฅผ ์žฌ์ •์˜ํ•œ ํด๋ž˜์Šค ๋ชจ๋‘์—์„œ hashCode๋„ ์žฌ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค. ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ HashMap์ด๋‚˜ HashSet ๊ฐ™์€ ์ปฌ๋ ‰์…˜์˜ ์›์†Œ๋กœ ์‚ฌ์šฉํ•  ๋•Œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ๊ฒƒ์ด๋‹ค.

๋‹ค์Œ์€ Object ๋ช…์„ธ์—์„œ ๋ฐœ์ทŒํ•œ ๊ทœ์•ฝ์ด๋‹ค.

  • equals ๋น„๊ต์— ์‚ฌ์šฉ๋˜๋Š” ์ •๋ณด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๊ทธ ๊ฐ์ฒด์˜ hashCode ๋ฉ”์„œ๋“œ๋Š” ๋ช‡ ๋ฒˆ์„ ํ˜ธ์ถœํ•ด๋„ ์ผ๊ด€๋˜๊ฒŒ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.
  • equals๊ฐ€ ๋‘ ๊ฐ์ฒด๋ฅผ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๋‹ค๋ฉด, ๋‘ ๊ฐ์ฒด์˜ hashCode๋Š” ๋˜‘๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.
  • equals๊ฐ€ ๋‘ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅด๋‹ค๊ณ  ํŒ๋‹จ ํ–ˆ๋”๋ผ๋„ ๋‘ ๊ฐ์ฒด์˜ hashCode๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

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

HashMap์€ ํ•ด์‹œ์ฝ”๋“œ๊ฐ€ ๋‹ค๋ฅธ ์—”ํŠธ๋ฆฌ๋ผ๋ฆฌ๋Š” ๋™์น˜์„ฑ ๋น„๊ต๋ฅผ ์‹œ๋„์กฐ์ฐจ ํ•˜์ง€ ์•Š๋„๋ก ์ตœ์ ํ™”๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋ณ„๋„์˜ ๊ฐ์ฒด๋ฅผ HashMap์˜ Key๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์›ํ•˜๋Š” ๊ฐ’์„ ๋ฆฌํ„ด ๋ฐ›์ง€ ๋ชปํ•  ๊ฒƒ์ด๋‹ค.

hashmap ๋™๋“ฑ ๋น„๊ต ๊ณผ์ •

image

๋™๋“ฑ์„ฑ์ด๋ž‘ ๋™์ผ์„ฑ์€ ๋ฌด์—‡์ผ๊นŒ?
๋™๋“ฑ์„ฑ(๋™์น˜์„ฑ) : ๋‘ ๊ฐ์ฒด๊ฐ€ ๋™์ผํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š”์ง€?
๋™์ผ์„ฑ : ๋‘ ๊ฐ์ฒด๊ฐ€ ๋ฌผ๋ฆฌ์ (์ฃผ์†Œ)์œผ๋กœ ๊ฐ™์€์ง€?

    @Override public int hashCode() { return 42; }

์ด ์ฝ”๋“œ๋Š” ๋™์น˜์ธ ๋ชจ๋“  ๊ฐ์ฒด์—์„œ ๋˜‘๊ฐ™์€ ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋‹ˆ ์ ๋ฒ•ํ•˜๋‹ค. ํ•˜์ง€๋งŒ ๋”์ฐํ•˜๊ฒŒ๋„ ๋ชจ๋“  ๊ฐ์ฒด์—๊ฒŒ ๋˜‘๊ฐ™์€ ๊ฐ’๋งŒ ๋‚ด์–ด์ฃผ๋ฏ€๋กœ ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ํ•ด์‹œํ…Œ์ด๋ธ”์˜ ๋ฒ„ํ‚ท ํ•˜๋‚˜์— ๋‹ด๊ฒจ ๋งˆ์น˜ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค.

์ข‹์€ ํ•ด์‹œ ํ•จ์ˆ˜๋ผ๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์— ๋‹ค๋ฅธ ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค

๋‹ค์Œ์€ hashCode๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์š”๋ น์ด๋‹ค.

  • ๊ฐ์ฒด์˜ ๋‚˜๋จธ์ง€ ํ•ต์‹ฌ ํ•„๋“œ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ํ•ด๋‹น ํ•„๋“œ์˜ ํ•ด์‹œ์ฝ”๋“œ 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์„ ์‚ฌ์šฉํ–ˆ์„๊นŒ?

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์€ ์ด๋Ÿฐ ์ตœ์ ํ™”๋ฅผ ์ž๋™์œผ๋กœ ์‹คํ–‰ํ•œ๋‹ค. https://i.ibb.co/d0p2zhx/Java-equals-and-hash-Code-Journal-Dev-2020-04-04-00-35-08.png
  • Q2. 31์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ง์ˆ˜๋‚˜ ๋‹ค๋ฅธ ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋Š” ์ด์Šˆ๊ฐ€ ๋ฌด์—‡์ผ๊นŒ?
    • ์†Œ์ˆ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฑด ์ •๋ณด๋ฅผ ์†์‹คํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‹ค.(๊ตฌ์ฒด์ ์ธ ์ •๋ณด ์†์‹ค์€ ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์Œ)
    • ์†Œ์ˆ˜ ์ค‘์— 31์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์‹œํ”„ํŠธ์™€ ๋บ„์…ˆ์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์–ด JVM ๋‚ด๋ถ€์ ์œผ๋กœ ์ตœ์ ํ™”ํ•ด์„œ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. (31 * i == (i << 5) - i)

์ฐธ๊ณ 

โš ๏ธ **GitHub.com Fallback** โš ๏ธ