자바 hashCode()와 equals()가 사용 하 는 장면
10843 단어 자바
hashCode()의 역할 은 해시 코드 를 얻 는 것 이 고 해시 코드 라 고도 부른다.그것 은 실제로 int 정 수 를 되 돌려 줍 니 다.이 해시 코드 의 역할 은 이 대상 이 해시 표 에 있 는 색인 위 치 를 확인 하 는 것 이다.
hashCode()는 JDK 의 Object.java 에 정의 되 어 있 습 니 다.이것 은 자바 의 모든 클래스 에 hashCode()함수 가 포함 되 어 있 음 을 의미 합 니 다. 자바 클래스 마다 hashCode()함수 가 포함 되 어 있 지만.그러나'클래스 의 산 목록'('산 목록'은 아래 설명 참조)을 만 들 때 만 이 클래스 의 hashCode()가 유용 합 니 다.(역할 은 이 클래스 의 모든 대상 이 산 목록 에 있 는 위 치 를 확인 하 는 것 입 니 다.다른 경우(예 를 들 어 클래스 의 단일 대상 을 만 들 거나 클래스 의 대상 배열 을 만 드 는 등)클래스 의 hashCode()는 역할 을 하지 않 습 니 다. 위의 산 목록 은 자바 집합 에서 본질 적 으로 산 목록 의 클래스 를 말 합 니 다.예 를 들 어 HashMap,Hashtable,HashSet 등 입 니 다.
즉,hashCode()는 산 목록 에서 만 유용 하고 다른 상황 에 서 는 쓸모 가 없다 는 것 이다.산 목록 에서 hashCode()의 역할 은 대상 의 산 열 코드 를 가 져 와 이 대상 이 산 목록 에 있 는 위 치 를 확인 하 는 것 입 니 다.
OK!이로써 우 리 는 해시 코드()의 역할 은 해시 코드 를 얻 는 것 임 을 알 게 되 었 다.그런데 해시 코드 는 무엇 에 쓰 입 니까?왜 산 목록 에 산열 코드 가 필요 합 니까?이 문제 들 을 해결 하려 면 해체 목록 이 필요 하 다!산 목록 의 내용 에 대해 서 는 두 세 마디 로 설명 하지 않 는 다.여러분 은 아래 의 몇 편의 문장 을 통 해 배 울 수 있 습 니 다.
[전재]산 목록(Hash Table)이론 에서 실 용(상)
[전재]산 목록(Hash Table)이론 에서 실 용(중)
[전재]산 목록(Hash Table)이론 에서 실 용적(하)
뒤의 내용 을 이해 할 수 있 도록 해시 코드 의 역할 을 간단하게 소개 합 니 다.
, (key-value), : “ ” “ ”。 !
。 “ ” , 。 , “ ” ; , , “ ” 。
다음은 HashSet 을 예 로 들 어 hashCode()의 역할 을 깊이 설명 하 겠 습 니 다.
만약 에 HashSet 에 1000 개의 요소 가 있다 고 가정 합 니 다.1001 번 째 요 소 를 삽입 할 때 어떻게 처리 해 야 합 니까?HashSet 은 Set 집합 이기 때문에 중복 요 소 를 허용 합 니 다. “"1001 번 째 요 소 를 각각 앞의 1000 개의 요소 와 비교 합 니까?"분명히 이 효율 은 똑 같이 낮다.산 목록 은 이 문 제 를 잘 해결 했다.요소 의 산열 코드 에 따라 요소 가 산 목록 에 있 는 위 치 를 계산 한 다음 에 요 소 를 이 위치 에 삽입 하면 된다.같은 요소 에 대해 서 는 당연히 하나만 저장 되 어 있다. 이 를 통 해 알 수 있 듯 이 두 요소 가 같 으 면 그들의 해시 코드 는 반드시 같다.하지만 반대로 꼭 그렇지 는 않다.산 목록 에서, 1.만약 에 두 대상 이 같다 면 그들의 hashCode()값 은 반드시 같 아야 한다. 2.만약 에 두 대상 이 hashCode()가 같다 면 그들 은 반드시 같 지 않다. 주의:이것 은 산 목록 에 있 는 상황 입 니 다.비산 목록 에서 반드시 이와 같 습 니 다!
'hashCode()의 역할'에 대해 이렇게 많은 이 야 기 를 나 누 었 다.
제4 부분 hashCode()와 equals()의 관계
이어서 우 리 는 다른 화 제 를 토론 합 시다.인터넷 상에 서 많은 글 들 이 hashCode()와 equals 를 관련 시 켰 는데 어떤 글 은 투철 하지 않 고 독 자 를 오도 한 혐의 가 있다.여기 서 나 는'hashCode()와 equals()의 관계'를 스스로 정리 했다.
우 리 는'클래스 의 용도'로'hashCode()와 equals()의 관계'를 두 가지 상황 으로 나 누 어 설명 한다.
1.첫 번 째 는'클래스 에 대응 하 는 산 목록'을 만 들 지 않 습 니 다.
여기 서 말 하 는'클래스 에 대응 하 는 산 목록 을 만 들 지 않 습 니 다'는 HashSet,Hashtable,HashMap 등 본질 적 으로 산 목록 의 데이터 구조 에서 이 종 류 를 사용 하지 않 습 니 다.예 를 들 어,이러한 종류의 HashSet 집합 을 만 들 지 않 습 니 다.
이런 상황 에서 이런 종류의'hashCode()와 equals()'는 반 마 오 관계 가 없다! 이 경우 equals()는 이러한 두 대상 이 같은 지 비교 하 는 데 사용 된다.hashCode()는 아무런 작용 이 없 기 때문에 hashCode()를 신경 쓰 지 않 아 도 된다.
다음은 예 시 를 통 해 클래스 의 두 대상 이 서로 같다 는 것 을 살 펴 보 겠 습 니 다. 그리고 시간 이 다 르 면 hashCode()의 값 을 추출 합 니 다.
원본 코드 는 아래 와 같다. (NormalHashCodeTest.java):
import java.util.*;
import java.lang.Comparable;
/**
* @desc equals() true false , hashCode() 。
*
* @author skywang
* @emai [email protected]
*/
public class NormalHashCodeTest{
public static void main(String[] args) {
// 2 Person ,
// equals
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)
", p1.equals(p2), p1.hashCode(), p2.hashCode());
System.out.printf("p1.equals(p3) : %s; p1(%d) p3(%d)
", p1.equals(p3), p1.hashCode(), p3.hashCode());
}
/**
* @desc Person 。
*/
private static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return name + " - " +age;
}
/**
* @desc equals
*/
public boolean equals(Object obj){
if(obj == null){
return false;
}
// true, false
if(this == obj){
return true;
}
//
if(this.getClass() != obj.getClass()){
return false;
}
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}
실행 결과:
p1.equals(p2) : true; p1(1169863946) p2(1901116749)
p1.equals(p3) : false; p1(1169863946) p3(2131949076)
결과 에서 도 알 수 있 듯 이 p1 과 p2 가 같은 상황 에서 hashCode()도 반드시 같 지 않다.
2.두 번 째 는'클래스 에 대응 하 는 산 목록'을 만 듭 니 다.
여기 서 말 하 는'클래스 에 대응 하 는 산 목록 을 만 들 것 입 니 다'는 HashSet,Hashtable,HashMap 등 본질 적 으로 산 목록 의 데이터 구조 에서 이 종 류 를 사용 할 것 입 니 다.예 를 들 어 이 종류의 HashSet 집합 을 만 듭 니 다.
이러한 상황 에서 이러한 종류의"hashCode()와 equals()"는 관계 가 있다. 1),만약 두 대상 이 같다 면 그들의 hashCode()값 은 반드시 같 을 것 이다. 여기 서 같은 것 은 equals()를 통 해 두 대상 을 비교 할 때 true 로 돌아 가 는 것 을 말한다. 2)만약 에 두 대상 이 hashCode()가 같다 면 반드시 같 지 않다. 산 목록 에서 hashCode()가 같 기 때문에 두 키 가 맞 는 해시 값 이 같 습 니 다.그러나 해시 값 이 같다 고 해서 키 값 이 일치 하 는 것 은 아니다."두 개의 서로 다른 키 값 이 맞 고 해시 값 이 같다"고 덧 붙 였 다.이것 이 바로 해시 충돌 이다.
그 밖 에 이런 상황 에서.두 대상 이 같은 지 판단 하려 면 equals()를 덮어 쓰 는 것 외 에 hashCode()함수 도 덮어 써 야 합 니 다.그렇지 않 으 면 equals()가 유효 하지 않 습 니 다.예 를 들 어 Person 류 의 HashSet 집합 을 만 들 려 면 Person 류 의 equals()와 hashCode()방법 을 동시에 덮어 써 야 합 니 다. equals()방법 만 덮어 쓰 면.우 리 는 equals()방법 이 우리 가 원 하 는 효과 에 이 르 지 못 했다 는 것 을 알 게 될 것 이다.
참조 코드 (ConflictHashCodeTest1.java):
import java.util.*;
import java.lang.Comparable;
/**
* @desc equals() true false , hashCode() 。
*
* @author skywang
* @emai [email protected]
*/
public class ConflictHashCodeTest1{
public static void main(String[] args) {
// Person ,
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
// HashSet
HashSet set = new HashSet();
set.add(p1);
set.add(p2);
set.add(p3);
// p1 p2, hashCode()
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)
", p1.equals(p2), p1.hashCode(), p2.hashCode());
// set
System.out.printf("set:%s
", set);
}
/**
* @desc Person 。
*/
private static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "("+name + ", " +age+")";
}
/**
* @desc equals
*/
@Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
// true, false
if(this == obj){
return true;
}
//
if(this.getClass() != obj.getClass()){
return false;
}
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}
실행 결과:
p1.equals(p2) : true; p1(1169863946) p2(1690552137)
set:[(eee, 100), (eee, 100), (aaa, 200)]
결과 분석:
우 리 는 Person 의 equals()를 다시 썼 다.그러나 이상 한 발견:HashSet 에는 중복 요소 가 있 습 니 다:p1 과 p2.왜 이런 상황 이 벌 어 졌 을 까?
p1 과 p2 의 내용 은 같 지만 hashCode()가 다 르 기 때문이다.그래서 HashSet 은 p1 과 p2 를 추가 할 때 같 지 않다 고 생각 합 니 다.
다음은 equals()와 hashCode()방법 을 동시에 덮어 씁 니 다.
참조 코드(ConflictHashCodeTest2.java):
import java.util.*;
import java.lang.Comparable;
/**
* @desc equals() true false , hashCode() 。
*
* @author skywang
* @emai [email protected]
*/
public class ConflictHashCodeTest2{
public static void main(String[] args) {
// Person ,
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
Person p4 = new Person("EEE", 100);
// HashSet
HashSet set = new HashSet();
set.add(p1);
set.add(p2);
set.add(p3);
// p1 p2, hashCode()
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)
", p1.equals(p2), p1.hashCode(), p2.hashCode());
// p1 p4, hashCode()
System.out.printf("p1.equals(p4) : %s; p1(%d) p4(%d)
", p1.equals(p4), p1.hashCode(), p4.hashCode());
// set
System.out.printf("set:%s
", set);
}
/**
* @desc Person 。
*/
private static class Person {
int age;
String name;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return name + " - " +age;
}
/**
* @desc hashCode
*/
@Override
public int hashCode(){
int nameHash = name.toUpperCase().hashCode();
return nameHash ^ age;
}
/**
* @desc equals
*/
@Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
// true, false
if(this == obj){
return true;
}
//
if(this.getClass() != obj.getClass()){
return false;
}
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}
실행 결과:
p1.equals(p2) : true; p1(68545) p2(68545)
p1.equals(p4) : false; p1(68545) p4(68545)
set:[aaa - 200, eee - 100]
결과 분석:
이제 equals()가 유효 합 니 다.HashSet 에는 중복 요소 가 없습니다. p1 과 p2 를 비교 한 결과,우 리 는 그들의 hashCode()가 같 고,equals()를 통 해 그것들 도 true 로 돌아 가 는 것 을 발견 했다.그래서 p1 과 p2 는 동일 하 게 여 겨 진다. p1 과 p4 를 비교 하면 우 리 는 그들의 hashCode()가 같 지만;그러나 equals()를 통 해 false 로 되 돌아 갑 니 다.그래서 p1 과 p4 는 같 지 않 은 것 으로 여 겨 진다.
전송:https://www.cnblogs.com/skywang12345/p/3324958.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.