문제

우리는 어떻게 결정에서의 최적 구현 hashCode() 방법은 컬렉션이(가정과 같은 방법이 다시 정의되었습니다.올바르게)?

도움이 되었습니까?

해결책

최 구현?그건 어려운 질문이기 때문에 그것을 사용 패턴에 따라.

또한 거의 모든 경우 합리적으로 구현되었고 조쉬 블로흐ko 효과적인 자바 에 항목이 8(second edition).가장 좋은 것은 그것을 찾기 때문에 저자명이 왜 이 방법이 좋다.

짧은 버전

  1. int result 및 할당 non-zero 값이 있습니다.

  2. 모든 분야 f 에서 테스트 equals() 방법,해시를 계산 코드 c 의:

    • 면 필 f boolean:계산 (f ? 0 : 1);
    • 면 필 f byte, char, shortint:계산 (int)f;
    • 면 필 f long:계산 (int)(f ^ (f >>> 32));
    • 면 필 f float:계산 Float.floatToIntBits(f);
    • 면 필 f double:계산 Double.doubleToLongBits(f) 고 핸들을 반환 값은 다음과 같 모든 장치
    • 면 필 f :를 사용하여 결과 hashCode() 방법는 경우에는 0 f == null;
    • 면 필 f 배열:모든 분야로 별도의 요소 계산 및 해쉬값을 재귀 패션 와 결합하는 값으로 다음에 설명하.
  3. 을 결합한 해쉬값 cresult:

    result = 37 * result + c
    
  4. Return result

이 결과는 적절한 분포 해시의 대부분의 값을 사용하여 상황입니다.

다른 팁

당신은 행복과 Java 효과적인 구현에 의해 추천 dmeister 사용할 수 있습니다,라이브러리 호출신의 회전이 자신의:

@Override
public int hashCode() {
    return Objects.hashCode(this.firstName, this.lastName);
}

이 필요로 하는 구아바(com.google.common.base.Objects.hashCode 다)또는 표준 라이브러리에서 Java7(java.util.Objects.hash 다)하지만 같은 방식으로 작동합니다.

그것은 더 나은 사용하는 기능을 제공하여 Eclipse 는 매우 좋은 일을 넣을 수 있습니다 당신의 노력과 에너지 개발에서 비즈니스 논리입니다.

하지만 이것이 연결 Android 문서(Wayback Machine)내 자신의 코드에 Github, 작동을 위한 Java 에서 일반적입니다.나의 응답의 확장 dmeister 의 응답 다만 코드는 많은 쉽게 읽고 이해할 수 있습니다.

@Override 
public int hashCode() {

    // Start with a non-zero constant. Prime is preferred
    int result = 17;

    // Include a hash for each field.

    // Primatives

    result = 31 * result + (booleanField ? 1 : 0);                   // 1 bit   » 32-bit

    result = 31 * result + byteField;                                // 8 bits  » 32-bit 
    result = 31 * result + charField;                                // 16 bits » 32-bit
    result = 31 * result + shortField;                               // 16 bits » 32-bit
    result = 31 * result + intField;                                 // 32 bits » 32-bit

    result = 31 * result + (int)(longField ^ (longField >>> 32));    // 64 bits » 32-bit

    result = 31 * result + Float.floatToIntBits(floatField);         // 32 bits » 32-bit

    long doubleFieldBits = Double.doubleToLongBits(doubleField);     // 64 bits (double) » 64-bit (long) » 32-bit (int)
    result = 31 * result + (int)(doubleFieldBits ^ (doubleFieldBits >>> 32));

    // Objects

    result = 31 * result + Arrays.hashCode(arrayField);              // var bits » 32-bit

    result = 31 * result + referenceField.hashCode();                // var bits » 32-bit (non-nullable)   
    result = 31 * result +                                           // var bits » 32-bit (nullable)   
        (nullableReferenceField == null
            ? 0
            : nullableReferenceField.hashCode());

    return result;

}

편집

일반적으로 무시할 때 hashcode(...), 에,당신은 또한 재정의 equals(...).그래서 그는 것이거나 이미 구현 equals, 여기에 좋은 참조 에서 내 Github...

@Override
public boolean equals(Object o) {

    // Optimization (not required).
    if (this == o) {
        return true;
    }

    // Return false if the other object has the wrong type, interface, or is null.
    if (!(o instanceof MyType)) {
        return false;
    }

    MyType lhs = (MyType) o; // lhs means "left hand side"

            // Primitive fields
    return     booleanField == lhs.booleanField
            && byteField    == lhs.byteField
            && charField    == lhs.charField
            && shortField   == lhs.shortField
            && intField     == lhs.intField
            && longField    == lhs.longField
            && floatField   == lhs.floatField
            && doubleField  == lhs.doubleField

            // Arrays

            && Arrays.equals(arrayField, lhs.arrayField)

            // Objects

            && referenceField.equals(lhs.referenceField)
            && (nullableReferenceField == null
                        ? lhs.nullableReferenceField == null
                        : nullableReferenceField.equals(lhs.nullableReferenceField));
}

첫째는지 확인 같은 구현했습니다.서 IBM DeveloperWorks 문서:

  • 대칭:두에 대한 참조,b,a.equals(b)는 경우에만 b.equals(a)
  • 상식적인:에 대한 모든 비 null 참조한다.equals(a)
  • 전이성:는 경우.equals(b)b.equals(c)음.equals(c)

다음 사항을 확인하십시오들의 관계가 차이를 존중하며 연락처(에서 동일한 문서):

  • 일관성과의 차이():두 개의 동일한 개체에 동일해야 합 차()값이

마지막으로 좋은 해쉬 기능을 위해 노력하는 접근 상 hash function.

about8.blogspot.com 말

는 경우 equals()true 를 반환하는 두 개체에 대해 다음의 차()한다 같은 값을 반환합니다.는 경우 equals()가 false 를 반환한 다음의 차()반환해야 합니다 다른 가치

나도 동의할 수 없습니다.는 경우 두 물체가 동일한 차이가 없을 의미하는 것은 그들이 동일하다.

는 경우 같 B 그 A. 해시 코드와 동일해야 B.hascode

는 경우 A. 차 equals B.hascode 는 것을 의미하지 않는 합 같 B

당신이 사용하는 경우 이클립스를 생성할 수 있습니다 equals()hashCode() 를 사용:

원본->성의 차이()및 equals().

이 기능을 사용하여 결정할 수 있습니다 어떤 분야 당신이 사용하고 싶은 평등과 해시 코드 계산 및 Eclipse 를 생성하는 해당 방법이 있습니다.

가의 구현 효과적인 자바ko hashcode()equals() 로직 Apache Commons Lang.체크아웃 HashCodeBuilderEqualsBuilder.

그냥 빠른 메모를 완료에 대한 더 자세한 답변(의 기간에 코드):

면을 고려 질문 -어떻게 나 만들기-해시 테이블에서 java 특히 jGuru FAQ 항목, 에,나는 믿고 일부는 다른 기준에는 해시 코드는 판단을 받은:

  • 동기화(않 algo 동시 지원에 액세스하거나지 않는)?
  • 가 안전하게 반복(않 algo 검색 컬렉션을 변경하는 동안 반복)
  • null 값(는 해시드 지원 null 값에서 컬렉션)

는 경우로,당신은 사용자 정의 컬렉션 클래스(예:새로운 클래스를 확장하는 컬렉션에서 인터페이스)을 구현하고자 해시()메소드가 있습니다.

는 경우에 당신의 컬렉션 클래스를 확장 AbstractList,당신은 걱정할 필요가 없이 그것에 대해 이미의 구현 equals()과의 차이()는 작품을 반복하여 모든 개체들 hashCodes()함께.

   public int hashCode() {
      int hashCode = 1;
      Iterator i = iterator();
      while (i.hasNext()) {
        Object obj = i.next();
        hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
      }
  return hashCode;
   }

면 지금 당신이 원하는 것은 최고의를 계산하는 방법에 대한 해시 코드는 특정 클래스 일반적으로 사용하^(비트는 독점 또는)운영자 프로세스는 모든 분야 내가 사용하는에서 같음 방법:

public int hashCode(){
   return intMember ^ (stringField != null ? stringField.hashCode() : 0);
}

@about8:가 꽤 심각한 버그가 있다.

Zam obj1 = new Zam("foo", "bar", "baz");
Zam obj2 = new Zam("fo", "obar", "baz");

같은 해시

무언가를 하고자 할 수도 있습니아

public int hashCode() {
    return (getFoo().hashCode() + getBar().hashCode()).toString().hashCode();

(당신이 얻을 수 있습니 차에서 직접 int 자바에서 이러한 일입니까?나도 그렇게 생각은 일부가 자동..이 경우에는 건너뛰 toString,그것이다.)

으로 특별히 요청한 컬렉션,추적 측면이 다른 답변을 언급하지 않은 아직:A HashMap 예상하지 못한들 키를 변경해 해시 한 번 그들은 컬렉션에 추가됩니다.전체 목적에 적...

를 사용하여 반사 방법 Apache Commons EqualsBuilderHashCodeBuilder.

어떤 해싱하는 방법을 균등하게 분산 해쉬값을 통해 가능한 범위로 구현.보 효과적인 자바( http://books.google.com.au/books?id=ZZOiqZQIbRMC&dq=effective+java&pg=PP1&ots=UZMZ2siN25&sig=kR0n73DHJOn-D77qGj0wOxAxiZw&hl=en&sa=X&oi=book_result&resnum=1&ct=result ),좋은 팁은 거기에 차 구현에(항목 9 내가 생각하는...).

내가 선호하는 유틸리티를 사용하여 프롬 방법 Google 컬렉션에 lib 클래스에서는 개체 는록 하는데 도움이 됩니다.매우 자주 equalshashcode 방법은 IDE 의 템플릿,그래서 그들은 청소하지 않습니다.

내가 사용하는 작은 래퍼 Arrays.deepHashCode(...) 처리하기 때문에 배열로 제공되는 매개 변수를 올바르

public static int hash(final Object... objects) {
    return Arrays.deepHashCode(objects);
}

여기에는 다른 JDK1.7+접근 방식 시연과 함께 수퍼 클래스 로직 를 차지.내가 그것으로 예쁜 convinient 개체 클래스의 차()를 차지했고,순수하는 JDK 의존성과 별도의 설명서 작동합니다.참고 Objects.hash() null 관대하다.

나는 포함하지 equals() 구현 하지만 현실에서 당신은 물론 필요합니다.

import java.util.Objects;

public class Demo {

    public static class A {

        private final String param1;

        public A(final String param1) {
            this.param1 = param1;
        }

        @Override
        public int hashCode() {
            return Objects.hash(
                super.hashCode(),
                this.param1);
        }

    }

    public static class B extends A {

        private final String param2;
        private final String param3;

        public B(
            final String param1,
            final String param2,
            final String param3) {

            super(param1);
            this.param2 = param2;
            this.param3 = param3;
        }

        @Override
        public final int hashCode() {
            return Objects.hash(
                super.hashCode(),
                this.param2,
                this.param3);
        }
    }

    public static void main(String [] args) {

        A a = new A("A");
        B b = new B("A", "B", "C");

        System.out.println("A: " + a.hashCode());
        System.out.println("B: " + b.hashCode());
    }

}

표준을 구현하는 것은 약하고 그것을 사용하여 이르는 불필요한 충돌 사고로 이어질 수 있습니다.상

class ListPair {
    List<Integer> first;
    List<Integer> second;

    ListPair(List<Integer> first, List<Integer> second) {
        this.first = first;
        this.second = second;
    }

    public int hashCode() {
        return Objects.hashCode(first, second);
    }

    ...
}

지금

new ListPair(List.of(a), List.of(b, c))

new ListPair(List.of(b), List.of(a, c))

hashCode, 즉 31*(a+b) + c 으로 승수 위해 사용됩 List.hashCode 재사용옵니다 여기에.물론,충돌을 피할 수 있지만,그 생산없이에 충돌이 단지...필요하다.

아무것도 없는 실질적으로 스마트 사용에 관하여 31.승수가 홀수이어야에서 손실을 방지하기 위해 정보(어떤 심지어 배율을 잃은 적어도 가장 중요한 비트,배수의 네 개의 두 가지를 잃고,etc.).어떤 이상한 배율을 사용할 수 있습니다.작은 승으로 이어질 수 있습 빠르게 연산(JIT 사용할 수 있는 교대 및 추가),하지만 주어진 것을 곱하기에는 대기 시간의 사이클에 현대적인 Intel/AMD,이는 거의 문제입니다.작은 승도 더 충돌에 대한 작은 입력에 문제가 될 수 있는 때때로.

를 사용하여 주는 의미로 소수에서 의미가 없습니다 링 Z/(2**32).

그래서 이 사용하는 것이 좋습 무작위로 선택된 큰 홀수(을 주시기 바랍 프라임).로 i86/amd64Cpu 사용할 수 있는 짧은 명령어를 피연산자 피팅에서 하나의 서명된 바이트가있는 작은 속도가 장점에 대한 승 같은 109.을 최소화 하기 위한 충돌,무언가를 가지고 다음과 같 0x58a54cf5.

를 사용하여 다른 곱셈기 다른 장소에서 유용하지만,충분하지 않을 정당화하는 작업이 요구됩니다.

를 결합하는 경우 해쉬값,일반적으로 사용하여 결합하는 방법에 사용되는 부 c++라이브러리,즉:

seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);

이것이 상당히 좋은 직장을 보장하는 고른 분포를 보여준다.에 대한 논의의 방법 이 수식의 작동,보의 유래 post: 마법수에서 부스트::hash_combine

좋은 토론의 다른 해쉬 기능: http://burtleburtle.net/bob/hash/doobs.html

에 대한 간단한 클래스에 그것은 종종 쉽게 구현하는 차()를 기반으로 클래스에있는 필드가에 의해 확인 equals()구현합니다.

public class Zam {
    private String foo;
    private String bar;
    private String somethingElse;

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

        if (obj == null) {
            return false;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        Zam otherObj = (Zam)obj;

        if ((getFoo() == null && otherObj.getFoo() == null) || (getFoo() != null && getFoo().equals(otherObj.getFoo()))) {
            if ((getBar() == null && otherObj. getBar() == null) || (getBar() != null && getBar().equals(otherObj. getBar()))) {
                return true;
            }
        }

        return false;
    }

    public int hashCode() {
        return (getFoo() + getBar()).hashCode();
    }

    public String getFoo() {
        return foo;
    }

    public String getBar() {
        return bar;
    }
}

가장 중요한 것은 유지하는 것입 차()및 equals()일관된:는 경우 equals()true 를 반환하는 두 개체에 대해 다음의 차()한다 같은 값을 반환합니다.는 경우 equals()가 false 를 반환한 다음의 차()반환해야 합니다 다른 값입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top