equals 방법과hashcode 방법
16875 단어 HashCode
Object의 equals는 두 대상의 메모리 주소를 비교하고hashcode 방법은 해시 코드 값으로 메모리 주소와 관련이 있고 int 값이다. 그러나hashcode 방법의 알고리즘은 대상 자체와 관련이 있다(jdk는 대상의 주소나 문자열이나 숫자에 따라 계산된다). 그래서 equals를 다시 쓸 때 대상 자체에 변화가 발생한다.물론 hashcode도 달라졌습니다. (Object 클래스에서 정의한hashCode 방법은 서로 다른 대상에 대해 서로 다른 정수를 되돌려줍니다)
A
다시 쓰기 전:
package collectionsFramework;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class HashSetTest {
public static void main(String[] args) {
Map<Student,String> m = new HashMap<Student,String>();
m.put(new Student(1,"zhangsan"), "aa");
m.put(new Student(1,"zhangsan"), "bb");
m.put(new Student(2," "), "cc");
System.out.println(new Student(1,"zhangsan") == new Student(1,"zhangsan"));
System.out.println(new Student(1,"zhangsan").equals(new Student(1,"zhangsan")));
Iterator<Entry<Student, String>> itmap = m.entrySet().iterator();
while (itmap.hasNext()) {
System.out.println(itmap.next());
System.out.println(m.get(new Student(1,"zhangsan")));
}
System.out.println();
HashSet<Student> hs = new HashSet<Student>();
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2," "));
Iterator<Student> itset = hs.iterator();
while (itset.hasNext()) {
System.out.println(itset.next());
System.out.println(m.get(new Student(1, "zhangsan")));
}
/*
* for(Iterator it = m.entrySet().iterator(); it.hasNext();){
* System.out.println(m.get(new Student(1, "zhangsan"))); }
*/
}
}
class Student {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return num + "+" + name + "+" + this.hashCode() + ";";
}
}
결과:
false
false
1+zhangsan+33263331;=bb
:-------null
1+zhangsan+12677476;=aa
:-------null
2+ +6413875;=cc
:-------null
1+zhangsan+28737396;
null
1+zhangsan+27744459;
null
2+ +6927154;
null
B
equals만 다시 쓰기
package collectionsFramework;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class HashSetTest {
public static void main(String[] args) {
//
}
}
class Student {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return num + "+" + name + "+" + this.hashCode() + ";";
}
public boolean equals(Object obj) {
if (null == obj) {
return false;
} else {
if (obj instanceof Student) {
Student o = (Student) obj;
if (this.name == o.name && this.num == o.num) {
return true;
}
}
return false;
}
}
}
결과:
false
true
1+zhangsan+33263331;=bb
:-------null
1+zhangsan+12677476;=aa
:-------null
2+ +6413875;=cc
:-------null
1+zhangsan+28737396;
null
1+zhangsan+27744459;
null
2+ +6927154;
null
표면상 new Student(1,"zhangsan").equals(new Student(1, "zhangsan")는true이지만 두'동일'대상은 모두hashmap의 키 값으로hashset에 저장되어 있습니다. 왜요?jdk는 당신처럼 간단한 equals가 아니기 때문에 두 대상을 비교할 때 대상의hash코드 값을 비교합니다. 하shcode()를 다시 쓸 때만hashcode가 일치할 때 상등합니다. 이로 인해hashset에 중복된 데이터가 있고hashmap에 같은 키가 있습니다. 이 같은 키를 사용하여value를 꺼낼 때 프로그램이 어떤 키를 호출했는지 몰라서value를 찾을 수 없습니다.쓰레기hashset과hashmap이 나왔어요.
C
hashcode만 다시 쓰기
package collectionsFramework;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class HashSetTest {
public static void main(String[] args) {
//
}
}
class Student {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return num + "+" + name + "+" + this.hashCode() + ";";
}
public int hashCode() {
return num * name.hashCode();
}
}
결과:
false
false
1+zhangsan+-1432604556;=bb
:-------null
1+zhangsan+-1432604556;=aa
:-------null
2+ +1362968;=cc
:-------null
1+zhangsan+-1432604556;
null
1+zhangsan+-1432604556;
null
2+ +1362968;
null
4
모두 다시 쓰기:
package collectionsFramework;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class HashSetTest {
public static void main(String[] args) {
//
}
}
class Student {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return num + "+" + name + "+" + this.hashCode() + ";";
}
public boolean equals(Object obj) {
if (null == obj) {
return false;
} else {
if (obj instanceof Student) {
Student o = (Student) obj;
if (this.name == o.name && this.num == o.num) {
return true;
}
}
return false;
}
}
public int hashCode() {
return num * name.hashCode();
}
}
결과:
false
true
1+zhangsan+-1432604556;=bb
:-------bb
2+ +1362968;=cc
:-------bb
1+zhangsan+-1432604556;
bb
2+ +1362968;
bb
두 번째 코드의 운행 결과를 보면 equals를 다시 쓰기만 하면 된다는 것을 알 수 있다.
그러나 new Student(1, "zhangsan")은 모두 Hashset(대상이 같지 않고 hashcode 값이 다르다는 뜻)에 저장되고,hashmap에서 m.get(new Student(1, "zhangsan"))은null,
new Student(1, "zhangsan")은 두 개의 값에 대응한다. "aa", "bb", 모순되어 키값으로 사용할 수 없다.
그래서 이때hashcode를 동시에 다시 써야 합니다. 그 다음에hashset 뒤에 같은 것을 추가하면 이전에 추가한 것을 덮어씁니다. 그러면 하나만 추가됩니다.hashmap에는 두 대상이 같고 그 다음에 키 값으로 추가됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
EffectiveJava - 모든 객체에 공통적인 메서드equals 방법을 덮어쓰지 않을 때, 클래스의 모든 실례는 그 자체와 같다 예를 들어 Random은 equals 방법을 실현하여 두 Random이 발생하는 무작위 수가 같은지 판단하는데 사용하지만 디자이너는 클라이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.