๐Ÿค” ์ด ๊ธ€์€ ์ž‘์„ฑ์ž์˜ ์ดํ•ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ž‘์„ฑ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๋‚˜ ์ž˜๋ชป๋œ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"equals์™€ hashcode๋Š” ๊ฐ™์ด ์žฌ์ •์˜ ๋˜์–ด์•ผํ•œ๋‹ค."

1. Java ์—์„œ String์€ ์™œ equals๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๋น„๊ตํ•ด์•ผํ• ๊นŒ?

Java๋ฅผ ์ฒ˜์Œ ์ ‘ํ–ˆ์„๋•Œ ์ ์‘ ์•ˆ๋˜์—ˆ๋˜๊ฒƒ๋“ค์ค‘ ํ•˜๋‚˜๊ฐ€ String์„ ๋น„๊ตํ• ๋•Œ๋Š” == ๋“ฑํ˜ธ ๋น„๊ต๊ฐ€์•„๋‹Œ String.equals(str) ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•œ ๋น„๊ต์˜€๋‹ค.

String a =new String("๋™์ผ์„ฑ");
String b =new String("๋™์ผ์„ฑ");
System.out.println(a==b);// false

2. ๋™๋“ฑ์„ฑ๊ณผ ๋™์ผ์„ฑ (identity and equality)

๊ฐ์ฒด๋น„๊ต์˜ == ์ฐธ์กฐํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋น„๊ตํ•˜๊ฒŒ๋œ๋‹ค.(์ด๊ธ€์—์„œ๋Š” ์„ค๋ช…์€ ์ƒ๋žต) ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์ด๋Š” ๋™์ผ์„ฑ ์„ ๋งŒ์กฑํ•œ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ String ์ด๋‚˜ ๊ธฐํƒ€ ๋‹ค๋ฅธ๊ฐ’์„ ๋น„๊ตํ• ๋–„ ๋ฌธ์ž์—ด ๊ฐ’ ์ž์ฒด์˜ ๋น„๊ต๋ฅผ ์›ํ• ๊ฒƒ์ด๋‹ค. ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‹ค๋ฅด๋”๋ผ๋„ ๊ฐ’์ด ๊ฐ™์€๊ฒฝ์šฐ ์ฆ‰ ๋™๋“ฑ ํ•œ์ง€ ๋น„๊ตํ•˜๊ณ ์ž ํ•œ๋‹ค. ๊ฐ’์˜ ์ผ์น˜์—ฌ๋ถ€๋ฅผ ๋™์ผ์„ฑ ์ด๋ผํ•œ๋‹ค

3. String์˜ equals๋Š” ์–ด๋–ค ๊ตฌ์กฐ์ผ๊นŒ?

Object class ์—์„œ ์ƒ์†๋ฐ›์€ equals ๋ฉ”์†Œ๋“œ๋ฅผ String ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์žฌ์ •์˜ ํ•œ๋‹ค.

//java 1.8์—์„œ String ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.  ์ด๋Š” ์ž๋ฐ” ๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ค๋ฅผ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜
public boolean equals(Object anObject) {
      if (this == anObject) {
          return true;
      }
      if (anObject instanceof String) {
          String anotherString = (String)anObject;
          int n = value.length;
          if (n == anotherString.value.length) {
              char v1[] = value;
              char v2[] = anotherString.value;
              int i = 0;
              while (n-- != 0) {
                  if (v1[i] != v2[i])
                      return false;
                  i++;
              }
              return true;
          }
      }
      return false;
  }

์ฝ”๋“œ๋ฅผ ์งง๊ฒŒ ๋ถ„์„ํ•ด๋ณด์ž๋ฉด ์ฒซ if๋ฌธ์—์„œ๋Š” ๋™์ผ์„ฑ์„ ๋น„๊ตํ•œ๋‹ค. ๊ฐ’๋น…๊ต์ด์ „์— ๋™์ผํ•œ ๊ฐ์ฒด์ผ๊ฒฝ์šฐ๋Š” ํ•ญ์ƒ ์ฐธ์ด๊ธฐ๋•Œ๋ฌธ์ด๋‹ค.
๋‘๋ฒˆ์งธ if๋ถ„๊ธฐ์—์„œ instanceof ๋กœ ๊ฐ์ฒดํƒ€์ž…์„ ๊ฒ€์‚ฌํ•˜๊ณ  String์ผ ๊ฐ’์„ char[] ๋ฐฐ์—ด๋กœ ์ˆœํšŒํ•˜๋ฉด์„œ ๋™๋“ฑ์„ฑ์„ ๋น„๊ตํ•œ๋‹ค.

4.์ž๋ฐ”์˜ hashcode

์ž๋ฐ” object๋Š” ๊ฐ ๊ณ ์œ ์˜ hash์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ ์ด๋Š” Object ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด์„œ ์ •์˜ํ•œ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ hashcode๋Š” ๊ฐ์ฒด์˜ ์ฃผ์†Œ๊ฐ’์„ ๋ณ€ํ™˜ํ•˜์—ฌ ์ƒ์„ฑํ•œ ๊ฐ์ฒด์˜ ๊ณ ์œ  ์ •์ˆ˜๊ฐ’์ด ์‚ฌ์šฉ๋˜๋ฉฐ ๋‘ ๊ฐ์ฒด๊ฐ€ ๋™์ผ ๊ฐ์ฒด์ธ์ง€ ๋น„๊ต ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. (๋™์ผ์„ฑ)
hashcode๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๊ฐ€ ๋™์ผ๊ฐ์ฒด์ž„์„ ๋น„๊ตํ•˜๋Š”๋ฐ ๋‹จ์ˆœ๊ฐ’์œผ๋กœ ๋น„๊ตํ•˜๋ฉด ๋˜๋ฏ€๋กœ O(1) ์‹œ๊ฐ„๋ณต์žก๋„๋กœ ๋น„๊ตํ• ์ˆ˜์žˆ๋‹ค.

4-1. hashcode๋Š” ์–ด๋””์„œ ์‚ฌ์šฉ๋ ๊นŒ?

HashMap,HashSet ๋“ฑ JCF(Java Collection Framework) ์—์„œ ๊ฐ์ฒด๊ฐ„์˜ ๋™์ผ์„ฑ์„ ๋น„๊ตํ• ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

4-2. hashcode๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š์•˜์„๋–„ ๋ฐœ์ƒํ• ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ .

public class IDCard {
String owner;

@Override
public boolean equals(Object obj) {
    if (this==obj){
      return true;
    }
    if (obj instanceof IDCard){
      return this.owner.equals(((IDCard) obj).owner);
    }
    return false;
  }

}

ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉ๋  ์ฝ”๋“œ์ด๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ IDCard๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด equals์™€ hashcode์— ๊ด€ํ•œ ํ…Œ์ŠคํŠธ ๋ช‡๊ฐ€์ง€๋ฅผ ์ง„ํ–‰ํ•˜๋ ค ํ•œ๋‹ค.

// ๋™๋“ฑ์„ฑํ…Œ์ŠคํŠธ

 @Test
void equals_test(){
    //given
    IDCard a_card=new IDCard("์ง€๋ฏผ");
    IDCard b_card=new IDCard("์ง€๋ฏผ");
    //when
    assertEquals(a_card,b_card);
    //then
}

์˜ˆ์ƒ๋Œ€๋กœ ์ž˜ํ†ต๊ณผํ•œ๋‹ค.

// set์„ ์ด์šฉํ•œ ์ค‘๋ณต์ œ๊ฑฐ ํ…Œ์ŠคํŠธ
@Test
void equals_noHashcode(){
    //given
  IDCard a_card=new IDCard("์ง€๋ฏผ");
  IDCard b_card=new IDCard("์ง€๋ฏผ");
    //when
  Set<IDCard> card_set=new HashSet<>();
  card_set.add(a_card);
  card_set.add(b_card);
  assertEquals(a_card,b_card);
  assertEquals(1,card_set.size());
}

equals๋กœ ๋น„๊ตํ–ˆ์„๋•Œ ๊ฐ™๋‹ค(๋™๋“ฑ) ํ•˜๊ธฐ์— Set์œผ๋กœ๋„ ์ค‘๋ณต์ œ๊ฑฐ๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋Š”๊ฑธ ์ƒ๊ฐํ–‡๋‹ค.

์™œ ๊ฐ™์€๊ฐ’์—๋Œ€ํ•œ ๊ฐ์ฒด๋น„๊ต์—์„œ ์ค‘๋ณต์ œ๊ฑฐ๋ฅผ ํ•˜์ง€๋ชปํ–ˆ์„๊นŒ?

๊ฐ„๋žตํ•˜๊ฒŒ ๋งํ•˜๋ฉด HashMap, HashSet ๋“ฑ์€ ๊ฐ์ฒด์˜ hashcode๋ฅผ ์ด์šฉํ•ด ๋จผ์ € ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•˜๊ณ  ๊ทธํ›„ equals ๋น„๊ต๋ฅผ ํ†ตํ•ด์„œ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€์ง€์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ๋‹ค. ์ฆ‰ ์˜์‚ฌ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ๊ฐ™๋‹ค.

 
 if (a.hashcode!=b.hashcode){
 	return false
 }
 else{
 	return a.equals(b)? true:false
 }
 

hashcode๋ฅผ ์žฌ์ •์˜ ํ•˜์ง€์•Š์„๊ฒฝ์šฐ ์ƒ์œ„ ํด๋ž˜์Šค์ธObject์˜ hash์ฝ”๋“œ์ธ ๋ฉ”๋ชจ๋ฆฌ๊ฐ’์—์˜ํ•œ hashcode๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด๊ฒฝ์šฐ ๊ฐ์ฒด์˜ ์ฃผ์†Œ๋กœ ๋™์ผ์„ฑ์„ ์ฒดํฌํ•˜๋ฏ€๋กœ ๋™๋“ฑ์„ฑ ๋น„๊ต์ด์ „์— hash์ฝ”๋“œ์—์„œ ์ด๋ฏธ ๊ฐ™์ง€์•Š์Œ์ด ํŒ๋ช…๋‚˜ ๋‹ค๋ฅธ๊ฐ’์œผ๋กœ ํŒ๋‹จํ•œ๋‹ค.

4-3 ์˜ˆ์ƒ๋™์ž‘์ด ๋˜๋„๋ก hashcode๋˜ํ•œ ์ •์˜ํ•ด์ฃผ๊ธฐ

public class IDCard2 extends IDCard{

public IDCard2(String owner) {
  super(owner);
}

@Override
public boolean equals(Object obj) {
  return super.equals(obj);
}

@Override
public int hashCode() {
  return this.owner.hashCode();
}
}

IDCard ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” IDCard2 ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  hashcode๋กœ๋Š” String ์ธ owner๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ String.hashcode๊ฐ€ ๋™์ž‘ํ•˜๋„๋กํ–ˆ๋‹ค.

IDCard2๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ์ฒด๋Š” ๊ฐ owner์˜ ์ด๋ฆ„์ด ๊ฐ™๋‹ค๋ฉด ๊ฐ™์€ hashcode๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค.์ด๋กœ Set์—์„œ๋„ ์ค‘๋ณต์ œ๊ฑฐ๊ฐ€ ์ž˜๋œ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ• ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๊ฒฐ๋ก 

JCF(java colleciton framework)๋ฅผ ์ด์šฉํ•˜๊ธฐ์œ„ํ•ด์„  hashcode ์žฌ์ •์˜๊ฐ€ ํ•„์ˆ˜์ ์ด๋‹ค. ๋งŒ์•ฝ ๋‹จ์ˆœ ๊ฐ์ฒด๋งŒ ์‚ฌ์šฉํ• ๊ฑฐ๋ผ hashcode ๋ฅผ ์“ฐ์ง€์•Š๋Š”๋‹ค๋ฉด ์ •์˜ํ•˜์ง€์•Š์•„๋„ ๋‹น์žฅ์˜ ์ฝ”๋“œ์ƒ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค์ง„ ์•Š๊ฒ ์ง€๋งŒ ์ž ์žฌ์ ์ธ ์ฝ”๋“œ์˜ ๋ณ€์น™์„ฑ์„ ์œ ๋ฐœํ• ๊ฒƒ์ด๋‹ค.

์ž ์žฌ์ ์œ„ํ—˜์„ ๋ฐœ๊ฒฌํ–ˆ๋Š”๋ฐ ๋ฐฉ์น˜ํ•˜๋Š”๊ฑด ๋ณ„๋กœ ์ข‹์ง€์•Š๋‹ค๋Š” ๊ฐœ์ธ์ ์ธ ์ƒ๊ฐ์ด๋‹ค.

์ถ”๊ฐ€์ ์œผ๋กœ
Lombok ์„ ์‚ฌ์šฉ์ค‘์ด๋ผ๋ฉด @EqualsAndHashCode ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๊ฐ„ํŽธํ•˜๊ฒŒ ์žฌ์ •์˜ํ• ์ˆ˜์žˆ๋‹ค.


์ฐธ๊ณ ํ•œ ๊ธ€

profile
tistory๋กœ ์ด์‚ฌ๊ฐ‘๋‹ˆ๋‹ค. :) https://feelingxd.tistory.com/

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2023๋…„ 7์›” 25์ผ

์ข‹์€ ์ •๋ณด ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
Powered by GraphCDN, the GraphQL CDN