문제

나는 평등이 2 개의 필드를 기반으로하는 클래스가있어 어느 쪽이든 동일하면이 유형의 객체가 동일하게 간주됩니다. equals ()에 대한 hashcode () 함수를 어떻게 작성하려면, 평등을 반환 할 때 해시 코드의 일반 계약이 동일하게되도록하는 방법은 무엇입니까?

public class MyClass {
  int id;
  String name;

  public boolean equals(Object o) {
    if (!(o instanceof MyClass))
      return false;
    MyClass other = (MyClass) o;
    if (other.id == this.id || other.name == this.name)
      return true;
    return false;
  }
}

이 클래스에 대한 hashcode () 함수를 어떻게 작성합니까? 그리고 나는 여기에서 상수로 돌아 오는 사소한 사건을 피하고 싶습니다.

public int hashCode() {
  return 1;
}
도움이 되었습니까?

해결책

사소한 해시 코드가 존재한다고 생각하지 않습니다. 또한, 당신의 equals() 일반 계약을 위반합니다 API에 언급되었습니다 --- 그것은이다 전이적이지 않습니다:

(1,2) 동등합니다 (1,3)

(4,3) 동등합니다 (1,3)

하지만 (4,3) ~이다 동일하지 않습니다 에게 (1,2).


완전성을 위해, 나는 당신에게 스키트-니코 증명 =)

주장하다: 해시 코드는 사소한 상수 기능이어야합니다.

증거: 허락하다 (a,b) 그리고 (c,d) 별개의 해시 코드가있는 두 개의 물체가 되십시오 h(a,b) ≠ h(c,d). 대상을 고려하십시오 (a,d). OP의 정의에 의해 (a,d) 와 동등하다 (a,b), 그리고 (a,d) 와 동등하다 (c,d). 그것은 다음에 따른다 해시 코드 계약 저것 h(a,d) = h(a,b) = h(c,d); 모순.

다른 팁

Ok, 시나리오에서 API 요구 사항을 1 초 동안 무시하면 비 정식 해시 기능이 없습니다.

다른 값을 가진 해시 장애가 있다고 상상해보십시오.

(a, b), (a, c), b! = c, 그 다음 해시 (a, b)! = hash (a, c), eventhough (a, b) = (a, c).

유사하게, (b, a) 및 (c, a)는 동일한 해시 코드를 방출해야합니다.

해시 기능 h라고 부르겠습니다. 우리는 찾는다:

h (x, y) = h (x, w) = h (v, w) x, y, v, w.

따라서 원하는 것을 수행하는 유일한 해시 기능은 일정합니다.

나는 Zach의 옳다고 확신합니다.이를 수행 할 사소한 해시 코드는 없습니다.

의사 방지 :

x = (id1, name1)과 y = (id2, name2)의 두 가지 비평 값을 고려하십시오.

이제 z = (id2, name1)를 고려하십시오. 이것은 x와 y와 동일하므로 x 및 y와 동일한 해시 코드를 가져야합니다. 따라서 x와 y는 동일한 해시 코드를 가져야합니다. 모두 값은 동일한 해시 코드를 가져야합니다.

이상한 상황에 처한 이유가 있습니다. X.equals (z) 및 Z.equals (y) 사실 ~해야 한다 x.equals (y)를 의미하지만 그렇지 않습니다. 평등의 정의는 평등의 정상적인 계약에 적합하지 않습니다.

나는 당신이 할 수 없다고 생각합니다. 그 이유는 당신의 것입니다 equals() 방법은 전이적이지 않습니다.

전이성은 3 개의 비 널 X, y, Z, if에 대한 수단 x.equals(y), y.equals(z), 그 다음에 x.equals(z). 당신의 예에서는 객체입니다 x={id: 1, name: "ha"}, y={id: 1, name: "foo"}, z={id: 2, name: "bar"} 이 속성이 있습니다 (x.equals(y) and y.equals(z)). 하지만, x.equals(z) ~이다 false. 모든 equals() 방법에는이 속성이 있어야합니다. Java API 문서를 참조하십시오.

해싱 함수로 돌아 가기 : 모든 함수는 f(x)==f(y). 즉, 함수 값의 비교에 관심이 있고 TRUE를 반환하기를 원한다면 x==y (아마도 다른 경우), 당신은 전이 관계를 받게 될 것입니다. 즉, 객체의 동등성을 적어도 전이적으로 폐쇄하는 것을 고려해야합니다. 귀하의 경우, 전이 폐쇄는 사소한 관계입니다 (모든 것은 무엇이든 동일합니다). 즉, 다른 객체를 어떤 함수로 구별 할 수 없습니다.

ID가 동일하거나 이름이 동일 할 때와 같이 의도적으로 평등을 정의 했습니까?

당신이 "및"그리고 "당신의 해시 코드는 동일하거나 적은 (동일하게 사용하지 않는 필드를 사용하지 않는) 필드를 사용하여 계산해야한다면, 당신은 equals ()에 의해 계산되어야합니다 ().

당신이 "또는"당신이 당신의 r hashgcode는 실제로 의미가없는 해시 코드 계산에 ID 또는 이름을 포함하지 않아야한다는 것을 의미하는 경우.

편집 : 질문을주의 깊게 읽지 않았습니다.

--

커먼즈 라인 항아리를 사용하겠습니다.

XOR 회원 해시 코드가 작동해야합니다. hashcode ()와 equals ()를 올바르게 구현해야합니다.

그러나 해시 코드를 보호하지 않으면 코드가 잘못 될 수 있습니다. 해시되면 변경해서는 안됩니다. 일어나지 않아야합니다.

public hashCode(){
   return new AssertionError();
}

또는

 public class MyClass {
   final int id;
   final String name;
   // constructor
 }

또는

public class MyClass {
   private int id;
   private String name;
   boolean hashed=false;
   public void setId(int value){
     if(hashed)throw new IllegalStateException();
     this.id=value;
   }
   public void setName(String value){
     if(hashed)throw new IllegalStateException();
     this.name=value;
   }
   // your equals() here
   public hashCode(){
     hashed=true;
     return new HashCodeBuilder().append(id).append(name).toHashCode();
   }
}

질문을 다시 읽은 후.

다른 필드가 업데이트 될 때 다른 필드를 자동으로 완성 할 수 있습니다.

--

편집 : 내 코드는 내 영어보다 더 잘 말할 수 있습니다.

void setName(String value){
  this.id=Lookup.IDbyName(value);
}
void setID(String value){
  this.name=Lookup.NamebyId(value);
}

편집 2 :

ID & 이름을 모두 설정하지 않으면 항상 사실을 반환하기 때문에 질문의 코드가 잘못 될 수 있습니다.

부분적으로 부분적으로 수행하는 메소드를 실제로 원한다면 "partialequals ()"라는 이름의 API를 작성하십시오.

가장 간단한 경로는 각 개별 필드의 해시 코드를 xor하는 것입니다. 이것은 일부 상황에서 약간의 추악함이 있습니다 (예 : X, Y 좌표는 X와 Y를 뒤집을 때 동일한 해시를 가질 수있는 잠재적으로 열악한 상황을 유발합니다). 효율성을 위해 필요한 경우 충돌을 줄이기 위해 필요에 따라 조정하십시오.

이건 어때

public override int GetHashCode()
{
    return (id.ToString() + name.ToString()).GetHashCode();
}

기능은 Allways Allways "유효한"해시를 반환해야합니다 ...

편집 : 방금 사용한다는 것을 알았습니다.

어때

public override int GetHashCode()
{
    return id.GetHashCode() ^ name.GetHashCode();
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top