equals재정의할 때, hashCode도 같이 재정의해야 하는 이유를 알아보겠습니다.
value1
, value2
, value3
의 값을 맞추시오
public class Item {
String id;
public Item(String id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
Item item = (Item) o;
return id == item.id && Objects.equals(id, item.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
public static void main(String args[]) {
Item item1 = new Item("1");
Item item2 = new Item("2");
Map<Item, Integer> map = new HashMap<>();
map.put(item1, 11111);
map.put(item2, 22222);
Map<Item, Integer> map1 = map;
item1.id = "3";
Integer value1 = map.get(new Item("1"));
Integer value2 = map.get(item1);
Integer value3 = map.get(new Item("3"));
}
}
.
.
.
.
.
.
.
.
.
.
.
value1 : null
value2 : null
value3 : null
hash값을 사용하는 Collection(HashSet, HashMap, HashTable)은 동등성을 비교할 때,
equals뿐만 아니라 hashCode도 비교하기 때문입니다.
즉, 같은 같은 객체를 판단할 때, equals가 같다면 hashCode도 같아야하기 때문입니다.
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
...
if (((HashMap.Node)e).hash == hash && ((k = ((HashMap.Node)e).key) == key || key != null && key.equals(k)))
...
}
final HashMap.Node<K, V> getNode(int hash, Object key) {
HashMap.Node[] tab;
HashMap.Node first;
int n;
if ((tab = this.table) != null && (n = tab.length) > 0 && (first = tab[n - 1 & hash]) != null) {
Object k;
if (first.hash == hash && ((k = first.key) == key || key != null && key.equals(k))) {
return first;
}
HashMap.Node e;
if ((e = first.next) != null) {
if (first instanceof HashMap.TreeNode) {
return ((HashMap.TreeNode)first).getTreeNode(hash, key);
}
do {
if (e.hash == hash && ((k = e.key) == key || key != null && key.equals(k))) {
return e;
}
} while((e = e.next) != null);
}
}
return null;
}
두 객체가 동일한 객체인지 판단하는 method.
동일한 주소
를 가리킬 때 같다고 판단.
public boolean equals(Object obj) {
return this == obj;
}
객체의 메모리 주소를 integer값으로 반환한 값
public class Object {
...
public native int hashCode(); // OS의 메소드 사용
}
System.identityHashCode(obj); // == obj.hashCode()를 출력하는 것. 참고용