equals์ hashCodeํจ์ ๋ชจ๋ Java ๊ฐ์ฒด์ ๋ถ๋ชจ ๊ฐ์ฒด์ธ Object ํด๋์ค์ ์ ์๋์ด ์๋ค.
๋ฐ๋ผ์ ๋ชจ๋ ๊ฐ์ฒด๋ Object ํด๋์ค์ ์ ์๋ equals์ hashCodeํจ์๋ฅผ ์์๋ฐ๋๋ค.
๋์ผ์ฑ(Identity), ๋๋ฑ์ฑ(Equality)
ํจ์๋ฅผ ์ค๋ช ํ๊ธฐ ์ ์์๋๋ฉด ์ข์ ๊ฐ๋ ์ธ ๊ฒ ๊ฐ์์ ๋จผ์ ์ ๋ฆฌํ์๋ค.
๋์ผ์ฑ(Identity)
๋์ผ์ฑ์ ๋น๊ต ๋์์ ๋ ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ๊ฐ์์ ์๋ฏธํ๋ค.
์๋ฐ์์ ๋น๊ต์ฐ์ฐ์(==)๋ฅผ ํตํด ํ์ธํ ์ ์๋ค.
public class Main {
static class Person{
int age;
public Person(int age) {
this.age = age;
}
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = p1;
System.out.println(p1 == p2);
}
}
p2๋ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์๊ณ , p1์ ๋์ ๋ฐ๋๋ค.
์ฆ, p1๊ณผ p2๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ์์นํ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ค.
๊ฐ์ฒด๋ ๊ฐ์์ ๊ณ ์ ํ ์๋ณ์๊ฐ ์๋๋ฐ, ์ด ์๋ณ์๊ฐ ๊ฐ๋ค๋ฉด ๋์ผํ๋ค๊ณ ํ๋จํ๋ค.
๋๋ฑ์ฑ(Equality)
๋น๊ต ๋์์ ๋ ๊ฐ์ฒด๊ฐ ๋ ผ๋ฆฌ์ ์ผ๋ก ๋์ผํ ๊ฐ์ ๋ํ๋ด๊ณ ์๋์ง ๊ฒ์ฌํ๋ค.
์๋ฐ์ ๋๋ฑ์ฑ์ ๋น๊ตํ๊ธฐ ์ํด์๋ equals์ hashcode๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํด์ผ ํ๋ค. (ํจ์์ ๋ด์ฉ์ ์๋์ ์์ธํ ๋ค๋ฃฐ ์์ )
public class Main {
static class Person{
int age;
public Person(int age) {
this.age = age;
}
}
@Override
public int hashCode() {
...
}
@Override
public boolean equals(Object obj) {
...
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1 == p2); // false
System.out.println(p1.equals(p2)); // true
}
}
p1๊ณผ p2๋ ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ๊ฐ์ง์ง๋ง 20์ด๋ผ๋ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ค.
๋ฐ๋ผ์ p1๊ณผ p2๋ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ฏ๋ก ๋๋ฑํ๋ค.
p1๊ณผ p2๋ฅผ ์์ ๋์ผ์ฑ์ ๋น๊ตํ๋ ๋น๊ต์ฐ์ฐ์(==)๋ก ๋น๊ตํ๋ฉด ๋ค๋ฅธ ์ฃผ์๊ฐ์ ๊ฐ์ง๋ฏ๋ก false๊ฐ์ด ์ถ๋ ฅ๋๋ค.
equals()
Objectํด๋์ค์ equals๋ฉ์๋
public boolean equals(Object obj) {
return (this == obj);
}
์ฝ๋๋ฅผ ๋ณด๋ฉด ๋น๊ต ์ฐ์ฐ์๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ๋น๊ตํ๊ณ ์๋ค.
์์์ ์ค๋ช ํ๋ ๊ฒ์ ๋ณด๋ฉด ๋น๊ต ์ฐ์ฐ์๋ ๊ฐ์ฒด์ ๋์ผ์ฑ(Identity)์ ๊ฒ์ฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
equals()์ override ํ์์ฑ
๊ธฐ์กด์ equals ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด์ ๊ฐ์ด ๊ฐ์๋ ๊ฐ์ฒด์ ์ฃผ์๊ฐ์ด ๋ค๋ฅด๋ฉด false๋ฅผ ๋ฆฌํดํ๋ค
ํ์ง๋ง ์ด๋ ์ปดํจํฐ์ ์ธ ๊ด์ ์์ ๋ฐ๋ผ๋ณธ ๊ฒ์ด๋ค.
์ธ๋ถ์ ์ธ ๊ด์ ์์๋ ๋ ๊ฐ์ฒด๋ ๋๊ฐ์ Person ํด๋์ค ํ์ ์ด๊ณ ๋๊ฐ์ ๋์ด ๊ฐ 20์ ๊ฐ์ง๊ณ ์๋ค.
์ฆ, ์ฌ์ฉ ์ ์ฅ์์๋ ๋ ๊ฐ์ฒด๋ ๊ฐ์ ๊ฐ์ฒด์ด๋ค..
๋ฐ๋ผ์ ๋๋ฑ์ฑ์ ์ํด ๊ฐ์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋น๊ตํ๋๋ก equals๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ์ฌ์ ์ํ๋ค.
equals() override
public class Main {
static class Person {
int age;
public Person(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(this.age, person.age);
}
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1.equals(p2));
}
}
์ฌ์ ์ํ ์ฝ๋๋ฅผ ํ ์ค์ฉ ์ดํด๋ณด์.
if (this == o) return true;
ํ์ฌ ๊ฐ์ฒด์ ๋งค๊ฐ๋ณ์์ ๊ฐ์ฒด๊ฐ ๊ฐ์ผ๋ฉด(๋์ผํ๋ฉด) true๋ฅผ ๋ฆฌํดํ๋ค.
๋ ๊ฐ์ฒด๊ฐ ๋์ผํ ๊ฒฝ์ฐ ์์ฐ์ค๋ฝ๊ฒ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๊ฒ ๋๋ฏ๋ก ๋๋ฑํ๋ค๊ณ ๋ณผ ์ ์๋ค.
if (o == null || getClass() != o.getClass()) return false;
๋งค๊ฐ๋ณ์ ๊ฐ์ฒด๊ฐ null์ด๊ฑฐ๋ Personํ์ ์ด ์๋๋ผ๋ฉด false๋ฅผ ๋ฆฌํดํ๋ค.
๋ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ํด๋์ค์ผ ๊ฒฝ์ฐ ๋๋ฑ์ฑ์ ๋น๊ตํ ํ์ ์์ด ๋ค๋ฅธ ๊ฐ์ด๋ค.
Person person = (Person) o;
return Objects.equals(this.age, person.age);
์์ ๊ฒฝ์ฐ๋ฅผ ๋ชจ๋ ํต๊ณผํ๋ค๋ฉด ์บ์คํ ์ ํตํด ๋งค๊ฐ๋ณ์์ ๊ฐ์ฒด๋ฅผ Personํ์ ์ผ๋ก ๋ณํํ๋ค.
๊ทธ ํ ๋ ๊ฐ์ฒด์ age ์ฆ, ๊ฐ์ ๋น๊ตํ์ฌ ๊ฐ์์ง ํ๋ณํ๋ค.
์ด๋ Objectsํด๋์ค์ equals๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
๐ค Objectsํด๋์ค์ equals๋ฉ์๋๋ override ํ equalsํจ์๋ ๋ด์ฉ์ด ๋๊ฐ์ ๊ฒ ๊ฐ์๋ฐ ๊ตณ์ด ์ ์ฌ์ ์๋ฅผ ํ ๊น?
์ฌ์ ์ํ ํจ์์์ Objects.equals๋ฉ์๋๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋ณด๊ณ "๊ทธ๋ผ ํด๋น ํจ์๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ๋ฉด ๋๋ ๊ฒ์ด ์๋๊ฐ?"๋ผ๋ ์๊ฐ์ด ๋ค์๋๋ฐ ์ฐฉ๊ฐ์ด์๋ค.
๊ฐ์ฒด ์์ฒด๋ฅผ equalsํจ์์ ๋ฃ๊ฒ ๋๋ฉด ๊ฒฐ๊ตญ return (a == b) || (a!= null && a == b)๊ฐ ๋๋ฏ๋ก ๋๋ฑ์ฑ์ ํ๋จํ ์ ์๋ค.
๋ฐ๋ผ์ ๋งค๊ฐ๋ณ์์ ๋น๊ตํ๊ณ ์ ํ๋ ๊ฐ์ ๋ฃ์ด์ ์ฌ์ ์ํ ๊ฒ์ด๋ค.
๐ก Objectํด๋์ค์ Objectsํด๋์ค ์ฐจ์ด
Object class
- java.langํจํค์ง์ ํฌํจ
- ๋ชจ๋ ์๋ฐ ํด๋์ค์ ์ต๊ณ ์กฐ์ ํด๋์ค
- ์๋ฐ์ ๋ชจ๋ ํด๋์ค๋ Object ํด๋์ค์ ๋ชจ๋ ๋ฉ์๋๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค.
Objects class
- java.util ํจํค์ง์ ํฌํจ
- ๊ฐ์ฒด ๋น๊ต, ํด์์ฝ๋ ์์ฑ, null ์ฌ๋ถ, ๊ฐ์ฒด ๋ฌธ์์ด ๋ฆฌํด ๋ฑ์ ์ฐ์ฐ์ ์ํํ๋ ์ ์ ๋ฉ์๋๋ค๋ก ๊ตฌ์ฑ๋ Object์ ์ ํธ๋ฆฌํฐ ํด๋์ค
+) ์ฐธ๊ณ
Stringํด๋์ค์๋ ์ด๋ฏธ ๋๋ฑ์ฑ์ ํ๋ณํ๋ equals๋ฉ์๋๊ฐ ์ ์๋์ด ์๋ค.
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
hashCode()
๊ฐ์ฒด์ ์ฃผ์ ๊ฐ์ ์ด์ฉํด์ ํด์ฑ(hashing) ๊ธฐ๋ฒ์ ํตํด ํด์ ์ฝ๋๋ฅผ ๋ง๋ ํ ๋ฐํํ๋ค.
์๋ก ๋ค๋ฅธ ๋ ๊ฐ์ฒด๋ ๊ฐ์ ํด์ ์ฝ๋๋ฅผ ๊ฐ์ง ์ ์๋ค.
์๋ฐํ ๋งํ๋ฉด ํด์ ์ฝ๋๋ ์ฃผ์๊ฐ์ ์๋๊ณ , ์ฃผ์๊ฐ์ผ๋ก ๋ง๋ ๊ณ ์ ํ ์ซ์๊ฐ์ด๋ค.
public class Main {
static class Person {
int age;
public Person(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(this.age, person.age);
}
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
Person p3 = p1;
System.out.println(p1.hashCode()); // 1521118594
System.out.println(p2.hashCode()); // 1940030785
System.out.println(p3.hashCode()); // 1521118594
}
}
Objectํด๋์ค์ hashcode๋ฉ์๋
public native int hashCode();
native ํค์๋๊ฐ ๋ค์ด๊ฐ ๋ฉ์๋๋ OS๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฉ์๋๋ฅผ ๋ปํ๋ค.
๐กJNI(Java Native Interface)
์๋ฐ ๊ฐ์๋จธ์ (JVM) ์์์ ์คํ๋๊ณ ์๋ ์๋ฐ์ฝ๋๊ฐ ๋ค์ดํฐ๋ธ ์์ฉ ํ๋ก๊ทธ๋จ(ํ๋์จ์ด์ ์ด์ ์ฒด์ ํ๋ซํผ์ ์ข ์๋ ํ๋ก๊ทธ๋จ๋ค) ๊ทธ๋ฆฌ๊ณ C, C++ ๊ทธ๋ฆฌ๊ณ ์ด์ ๋ธ๋ฆฌ ๊ฐ์ ๋ค๋ฅธ ์ธ์ด๋ค๋ก ์์ฑ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ํธ์ถํ๊ฑฐ๋ ๋ฐ๋๋ก ํธ์ถ๋๋ ๊ฒ์ ๊ฐ๋ฅํ๊ฒ ํ๋ ํ๋ก๊ทธ๋๋ฐ ํ๋ ์์ํฌ
์์์ ์ค๋ช ํ native ์ฝ๋ ์ค ํ๋๊ฐ hashCode() ๋ฉ์๋์ด๋ค.
์ด ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ OS์ C์ธ์ด๋ก ์์ฑ๋์ด ์์ด ๊ทธ ์์ ๋ด์ฉ์ ๋ณผ ์ ์๊ณ , ์ค๋ก์ง ์ฌ์ฉ๋ง ํ ์ ์๋ค. ๊ทธ๋์ ๋ง์น ์ถ์ ๋ฉ์๋์ฒ๋ผ ์ ์๋์ด ์๋ ๊ฒ์ด๋ค.
hashcode()์ override ํ์์ฑ
๐ค ์ hashcode()๋ equals()์ ํจ๊ป override ๋์ด์ผ ํ ๊น?
๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด ๋ ๋ฉ์๋๋ฅผ ๋ชจ๋ ์ฌ์ ์ํ์ง ์์ ์, Collection Framework(HashSet, HashMap, HashTable)์ ์ฌ์ฉํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์ฒ์ฒํ ์ดํด๋ณด์.
equals๋ง ์ฌ์ ์ํ ๊ฒฝ์ฐ
๐ List๋ฅผ ํตํ ์ถ๋ ฅ
public class Main {
static class Person {
int age;
public Person(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return age == person.age;
}
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1.hashCode()); // 1521118594
System.out.println(p2.hashCode()); // 1940030785
List<Person> people = new ArrayList<>();
people.add(p1);
people.add(p2);
System.out.println(people.size()); // 2
}
}
p1๊ณผ p2๊ฐ์ฒด๋ ํด์์ฝ๋, ์ฆ ์ฃผ์ ๊ฐ์ด ๋ค๋ฆ์๋ ๋ถ๊ตฌํ๊ณ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ๊ฐ์ฒด๊ฐ ๋๋ค.
๋ง์ง๋ง์ Person ๊ฐ์ฒด 2๊ฐ๋ฅผ ArrayList์๋ฃํ์ ๋ฃ์ ํ ๋ฆฌ์คํธ์ ํฌ๊ธฐ(๊ธธ์ด)๋ 2๊ฐ ์ถ๋ ฅ๋๋ค.
๐ Set์ ํตํ ์ถ๋ ฅ
๐จ์๊ตฌ์ฌํญ ์ถ๊ฐ๐จ
Collection์ ์ค๋ณต๋์ง ์๋ Person ๊ฐ์ฒด๋ง ๋ฃ์ด๋ผ.
public class Main {
...
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
Set<Person> people = new HashSet<>();
people.add(p1);
people.add(p2);
System.out.println(people.size()); // 2
}
}
List์๋ฃํ ๋์ ์ค๋ณต๋ ๊ฐ์ ํ์ฉํ์ง ์๋ Set ์๋ฃํ์ ์ด์ฉํด ๋ณด์.
ArrayList์์ HashSet์ผ๋ก ๋ณ๊ฒฝํ์๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ 2๊ฐ ๋์๋ค. (โโโ)
Person๊ฐ์ฒด์ age๊ฐ์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋ณํ๋๋ก equals๋ฉ์๋๋ฅผ ์ฌ์ ์ํ์์ผ๋ฏ๋ก ๊ฒฐ๊ณผ ๊ฐ์ 1์ด ๋์์ด์ผ ํ์ง๋ง ์ฐ๋ฆฌ์ ์์๊ณผ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค.
p1๊ณผ p2๊ฐ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ๋ค๊ณ ์ ์ํ์์ง๋ง ํด์์ฝ๋๊ฐ ๋ค๋ฅด๋ฏ๋ก ์ค๋ณต๋ ๋ฐ์ดํฐ๊ฐ ์ถ๊ฐ๋ ๊ฒ์ด๋ค.
hashCode์ equals ๋์ ์์
์์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ์ด์ ๋ hash ๊ฐ์ ์ฌ์ฉํ๋ Collection(HashMap, HashSet, HashTable)์ ๊ฐ์ฒด๊ฐ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์์ง ๋น๊ตํ ๋ ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ๊ณผ์ ์ ๊ฑฐ์น๊ธฐ ๋๋ฌธ์ด๋ค.
1. ๋ฐ์ดํฐ๊ฐ ์ถ๊ฐ๋๋ฉด ๊ทธ ๋ฐ์ดํฐ์ hashCode()์ ๋ฆฌํด ๊ฐ์ ๋น๊ตํ๊ณ ๊ฐ์ผ๋ฉด equals() ์คํ, ๋ค๋ฅด๋ฉด false๋ฅผ return ํ๋ค.
2. equals()์ ๋ฆฌํด ๊ฐ์ ๋น๊ตํ์ฌ ๊ฐ์ผ๋ฉด true๋ฅผ retun ํ๊ณ ๋ค๋ฅด๋ฉด false๋ฅผ return ํ๋ค.
๋ฐ๋ผ์ Personํด๋์ค์์ equals()๋ฅผ override ํ ๋ hashCode๋ฅผ override ํ์ง ์์ผ๋ฉด ๋ฐ๋ก false๋ฅผ ๋ฆฌํดํด ๋ค๋ฅธ ๊ฐ์ฒด๋ก ํ๋ณํ๊ฒ ๋๋ค.
=> ๋ฐ๋ผ์ equals๋ฉ์๋๋ฅผ ์ฌ์ ์ ํ ๋๋ ๊ผญ hashCode๋ฉ์๋๋ ์ฌ์ ์ ํด์ผ ํ๋ค.
hashCode() override
public class Main {
static class Person {
...
@Override
public boolean equals(Object o) {
...
}
@Override
public int hashCode() {
return Objects.hash(age);
}
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
Set<Person> people = new HashSet<>();
people.add(p1);
people.add(p2);
System.out.println(people.size()); // 1
}
}
๋ฐํ๋๋ ํด์์ฝ๋ ๊ฐ์ ๊ฐ์ฒด์ ์ฃผ์๊ฐ์ด ์๋ Person๊ฐ์ฒด์ age ๊ฐ์ ์ด์ฉํด ํด์์ฝ๋๋ฅผ ๋ฐํํ๋๋ก ํ๋ค.
๐ก Objects.hash()
public static int hash(Object... values) { return Arrays.hashCode(values); }
๋งค๊ฐ๋ณ์๋ก ์ฃผ์ด์ง ๊ฐ๋ค์ ์ด์ฉํด์ ๊ณ ์ ํ ํด์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
์ฆ, ๋์ผํ ๊ฐ์ ๊ฐ์ง๋ ๊ฐ์ฒด๋ค์ ํ๋๋ก ํด์์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด, ๋์ผํ ํด์์ฝ๋๋ฅผ ๊ฐ์ง ์ ์๊ฒ ๋์ด, ์ด ํด์์ฝ๋ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ฌ์ ์ํ equals()๊ฐ ๋๋ฑ ๋น๊ต์ ์ด์ฉํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
Objects.hash()๋ hashCode ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ๊ธฐ ์ํด ๊ฐํธํ ์ฌ์ฉํ ์ ์๋ ๋ฉ์๋์ด์ง๋ง ์๋๊ฐ ๋๋ฆฌ๋ค. ์ธ์๋ฅผ ๋ด๊ธฐ ์ํ ๋ฐฐ์ด์ด ๋ง๋ค์ด์ง๊ณ ์ธ์ ์ค ๊ธฐ๋ณธ ํ์ ์ด ์๋ค๋ฉด ๋ฐ์ฑ๊ณผ ์ธ๋ฐ์ฑ๋ ๊ฑฐ์ณ์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
๐ค ๊ฐ์ ์์ฒด์ ํด์์ฝ๋๋ฅผ ์ป๊ณ ์ถ์ผ๋ฉด ์ด๋กํ์ง? ์ด๋ฏธ hashCode๋ ์ฌ์ ์ํด์ ์ํ๋ ๊ฐ์ผ๋ก ๋ง๋ค์๋๋ฐ..
hashCode()์ ์๋ ๋ชฉ์ ์ ๊ฐ์ฒด์ ์ฃผ์๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ํด์ฑ์์ ๊ณ ์ ํ ์ซ์๊ฐ์ ๋ฐํํ์ฌ ์ด๋ฅผ ํตํด ๊ฐ์ฒด์ ๋์ผ์ฑ(identity)์ ํ๋จํ๋ ๊ฒ์ด๋ค
์๋์ hashCode๋ฅผ ๊ตฌํด์ผ ํ๋ ๊ฒฝ์ฐ identityHashCode()๊ฐ ์กด์ฌํ๋ค.
์ฆ, hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ ํด์ ์ฐ๋๋ฐ, ์ค๋ฒ๋ผ์ด๋ฉ ํ๊ธฐ ์ ์ ์์กฐ ๊ธฐ๋ฅ์ด ํ์ํ ๋ ์ฌ์ฉ ํ๋ ๋ฉ์๋์ด๋ค.
System.identityHashCode()๋ ๋ฐ๋ก ๋ ๋ฆฝ๋ ์์คํ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ์ฃผ์ ๊ฐ์ด ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ํด ํญ์ ๋ค๋ฅธ ํด์ ์ฝ๋๊ฐ์ ๋ฐํํ ๊ฒ์ ๋ณด์ฅํ๋ค.
์์
public class Main {
static class Person {
...
@Override
public boolean equals(Object o) {
...
}
@Override
public int hashCode() {
...
}
}
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1.hashCode()); // 51
System.out.println(p2.hashCode()); // 51
System.out.println(System.identityHashCode(p1)); // 1521118594
System.out.println(System.identityHashCode(p2)); // 1940030785
}
}
hashCode ์ฃผ์์ฌํญ
hashCode๊ฐ ๊ณ ์ ํ ๊ฐ์ ์๋๋ค!
๋ณดํต ํด์ฑ ์๊ณ ๋ฆฌ์ฆ ์ ์๋ก ๋ค๋ฅธ ๋ ์ฃผ์๊ฐ์ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ฒด๋ ๊ฒฐ์ฝ ๊ฐ์ ํด์์ฝ๋๋ฅผ ๊ฐ์ง ์ ์๋ค. ํ์ง๋ง ์์ธ๊ฐ ์๋๋ฐ, ๋ฐ๋ก hashCode() ๋ฉ์๋๊ฐ intํ ์ ์๋ฅผ ๋ฐํํ๋ค๋ ์ ์ด๋ค.
64๋นํธ ์ปดํจํฐ์์ ๋์๊ฐ๋ JVM(๊ฐ์๋จธ์ )์ ๊ธฐ๋ณธ์ ์ผ๋ก 8๋ฐ์ดํธ(64bit) ์ฃผ์์ฒด๊ณ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ํ๋๋ฐ, ๋ง์ผ 8๋ฐ์ดํธ์ ์ฃผ์๊ฐ์ hashCode๋ฅผ ์ด์ฉํด ๋ฐํํ๋ฉด ๋ฉ์๋์ ํ์ ์ ๋ฐ๋ผ 4๋ฐ์ดํธ(32bit)๋ก ๊ฐ์ ์บ์คํ (long → int)์ด ๋๊ธฐ ๋๋ฌธ์ ๊ฐ์ด ๊ฒน์น ์๋ ์๋ค๋ ์ผ์ด์ค๊ฐ ์กด์ฌํ๊ฒ ๋๋ค. (Hash Collisions)
ํ์ง๋ง ๊ฐ์ฒด๋ฅผ ๋น๊ตํ ๋ ์ด๊ฒ์ ํฐ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค.
hashCode์ equals ๋์ ์์์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด ๋ ๊ฐ์ฒด๋ฅผ ๋น๊ตํ๋ ๊ณผ์ ์์ ๋ง์ผ ๋ ๊ฐ์ฒด์ ํด์ ์ฝ๋๊ฐ ๊ฐ์ผ๋ฉด equals() ๋ฉ์๋๋ฅผ ํตํด ๋ ๊ฐ์ฒด์ ์ง์ง ์ฃผ์๋ฅผ ์ง์ ์ ์ผ๋ก ๋น๊ตํ๋๋ก ๊ตฌ์ฑ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค. (๋์ผ์ฑ ๋น๊ต)
โ ์ ๋ฆฌ
ํด์์ฝ๋ ๊ฐ์ผ๋ก๋ง ๋ ๊ฐ์ฒด์ ๋๋ฑ์ ํ๋ณํ๋ ค ํ ๋ ์ด๋ฌํ ์์ธ์ ์ธ ์ผ์ด์ค๊ฐ ์๋ค๋ ๊ฒ์ ์ธ์งํ๊ณ ์์.
๐ ๊ฟํ!
Intellij์์ alt + insert๋ฅผ ๋๋ฅธ ํ equals ๋ฐ hashCode()๋ฅผ ํด๋ฆญํ๋ฉด ์๋์ผ๋ก ์ค๋ฒ๋ผ์ด๋ฉ๋ ๋ฉ์๋๋ฅผ ๋ง๋ค ์ ์๋ค.
Reference
๋์ผ์ฑ(Identity)๊ณผ ๋๋ฑ์ฑ(Equality) - hudi.blog
์๋ฐ equals / hashCode ์ค๋ฒ๋ผ์ด๋ฉ - ์๋ฒฝ ์ดํดํ๊ธฐ - Inpa Dev
equals์ hashCode๋ ์ ๊ฐ์ด ์ฌ์ ์ํด์ผ ํ ๊น? - Tecoble
Guide to hashCode() in Java - Baeldung(ํฅ์๋ hashCode() ๋ง๋ค ๋ ์ฐธ๊ณ )
'๐กCS > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Java] String, StringBuffer, StringBuilder (0) | 2023.06.09 |
---|---|
[Java] Call by value vs Call by reference (0) | 2023.06.08 |
์์ ํ์ (Primitive), ์ฐธ์กฐ ํ์ (Reference) (0) | 2023.06.07 |
์ ๊ทผ ์ ์ด์(private, default, protected, public) (0) | 2023.06.07 |
ํด๋์ค, ๊ฐ์ฒด, ์ธ์คํด์ค๋? (0) | 2023.06.07 |
๋๊ธ