자바 실체 재 작성 equals 와 hashcode 에 대하 여

3798 단어 지식 총화
최근 List 에서 HashSet 을 다시 쓰 려 고 합 니 다. equals 와 hashcode 를 다시 쓰 는 문제 가 발생 했 습 니 다. 기록 하 십시오:
이것 은 Object 류 가 이 두 가지 방법 에 관 한 소스 코드 입 니 다.
    public native int hashCode();

    public boolean equals(Object obj) {
        return (this == obj);
    }

Object 류 의 기본 equals 비교 규칙 은 두 대상 의 메모리 주 소 를 비교 하 는 것 임 을 알 수 있 습 니 다.그래서 무 거 운 것 을 진행 할 때 equals 를 다시 써 야 합 니 다.
public class EntAlterListEntity {

    private String altItem;
    private Date altDate;
    
	public String getAltItem() {
		return altItem;
	}
	public void setAltItem(String altItem) {
		this.altItem = altItem;
	}
	public Date getAltDate() {
		return altDate;
	}
	public void setAltDate(Date altDate) {
		this.altDate = altDate;
	}

   @Override
   public boolean equals(Object o) {
       if(this == o){
           return true;
       }
       if(o == null){
           return false;
       }
 
       if(getClass() != o.getClass()){
           return false;
       }
       EntAlterListEntity entAlter = (EntAlterListEntity) o;
       //altDate  
       if(altDate == null){
           if(entAlter.altDate !=null){
               return false;
           }
       }else{
    	   if(altDate.compareTo(entAlter.altDate)!=0){
	           return false;
    	   }
       }
       //altItem  
       if(!StringUtils.equals(altItem, entAlter.altItem)){
           return false;

       return true;
   }
}

한편, hashcode 는 로 컬 방법 으로 자바 의 메모리 가 안전 하기 때문에 해시 코드 에 따라 대상 의 메모리 주 소 를 얻 을 수 없 지만 실제 hashcode 는 대상 의 메모리 주소 에 따라 해시 알고리즘 을 통 해 얻 은 것 입 니 다.ArrayList 는 hashCode 가 같 지 않 든 equals 에 따라 포함 여 부 를 판단 합 니 다.한편, HashSet 처리 절 차 는 다 릅 니 다. 먼저 두 대상 의 hashCode 방법 이 같 는 지 판단 하고 다 르 면 두 대상 의 equals 가 같 지 않다 고 생각 하고 equals 방법 을 호출 하지 않 습 니 다. hashCode 가 같 을 때 equals 방법 에 따라 두 대상 이 같 는 지 판단 합 니 다 (해시 데이터 의 빠 른 액세스).즉시 hashCode 방법의 일반적인 협정:
(1) obj 1. equals (obj 2) 가 true 일 때 obj 1. hashCode () = = obj 2. hashCode () 는 true 여야 합 니 다.  (2) obj 1. hashCode () = = obj 2. hashCode () 가 false 일 때 obj 1. equals (obj 2) 는 false 여야 합 니 다.
그럼 해시 코드 를 어떻게 다시 쓰 나 요?
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + (altItem== null ? 0 : altItem.hashCode());
        result = 31 * result + (altDate== null ? 0 : altDate.hashCode());
        return result;
    }

int 형식의 변수 result 를 만 들 고 값 을 초기 화 합 니 다. 예 를 들 어 17. 그 다음 에 클래스 의 모든 중요 한 필드, 즉 대상 의 값 에 영향 을 주 는 필드, 즉 equals 방법 에 비교 하 는 필드 가 있 습 니 다. 다음 작업 을 수행 합 니 다. a. 이 필드 의 값 을 계산 합 니 다 filed HashValue = filed. hashCode ().b. 실행 result = 31 * result + filedHashValue;
왜 31 을 사용 합 니까?다음은 String hashCode 방법의 소스 코드 입 니 다.
 /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * 

     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * 
* using {@code int} arithmetic, where {@code s[i]} is the
* ith character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
곱 하기 충돌 을 줄 이 고 최적화 할 수 있다.
* 왼쪽으로 이동 <: 왼쪽 의 최고 위 를 버 리 고 오른쪽 에 0 (< 왼쪽 의 데이터 * 2 의 이동 차 멱) * 오른쪽으로 이동 > >: > 왼쪽 의 데이터 / 2 의 이동 차 멱 * 기호 없 이 오른쪽으로 이동 > >: 최고 위 가 0 이 든 1 이 든 왼쪽 에 0 을 보충 합 니 다.
 그래서: 31 * i = (i < 5) - i (왼쪽  31 * 2 = 62, 오른쪽   2 * 2 ^ 5 - 2 = 62) - 양쪽 이 같 으 면 JVM 이 효율적으로 계산 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기