2014-12-25 3 views
-1

개체 (BookMe)의 hashcode 메서드를 재정의 한 후 아래 코드를 실행하고 있습니다. 목표는 내지도 (해시 맵)에서 키로 사용할 객체의 해시 코드를 재정의하는 것입니다. 하지만, 실행 후 null 값을 참조하십시오. 지도의 실제 크기에는 아무런 문제가 없습니다. 아래는 코드입니다. 해시 코드 메서드를 재정의하지 않으면 올바른 출력을 얻습니다. (나는 세 가지 값 모두를 의미합니다). `해시 코드 메서드를 재정의하는 동안 hashmap에서 올바른 값을 가져올 수 없습니다.

class BookMe{ 
private String isbn ; 
static int i = 0; 
public BookMe(String isbn) 
{ 
    this.isbn = isbn;  
} 
public String getIsbnValue() 
{ 
    return this.isbn; 
} 
@Override 
public boolean equals(Object o) 
{ 
    if(o instanceof BookMe && ((BookMe)o).getIsbnValue() == this.getIsbnValue()) 
    { 
     return true; 
    } 
    else{ 
     return false; 
    } 
} 
@Override 
public int hashCode() 
{ 
    return this.isbn.toString().length() + (++i); 
} 

}

공용 클래스 HashMapTest는 {

public static void main(String[] args) { 

    Map<BookMe, Integer> map = new HashMap<BookMe, Integer>(); 

    BookMe b1 = new BookMe("Graham"); 
    BookMe b2 = new BookMe("Graham"); 
    BookMe b3 = new BookMe("Graham"); 
    map.put(b1, 19); 
    map.put(b2, 33); 
    map.put(b3, 22); 

    System.out.println("----444444--------"); 
    System.out.println(map.size()); 

    Set <BookMe> set = map.keySet(); 
    System.out.println("------*****------"); 


    for(BookMe bk : set) 
    { 
     System.out.println("bk : "+ bk); 
     System.out.println(map.get(bk)); 
    }  
} 

} `

+0

정적 필드를 수정하고이를 사용하여 반환 된 해시 코드에 영향을줍니다. 즉, 같은 객체가 반복 호출에서 동일한 해시 코드를 제공하지 않습니다. 그것은 해시 코드로서 완전히 쓸모가 없습니다. – khelwood

+0

이것은 문제의 가능한 원인입니다.'(BookMe) o) .getIsbnValue() == this.getIsbnValue()'. 자세한 설명은 Q & A를 참조하십시오. –

+0

@Stephen ... 변경했습니다. 오류를 이해했으며, 간과 된 코드 오류가 있으며 "같음"으로 수정했습니다. 그건 내 주장이 아닙니다. Eran의 회신에서 제 3의 코멘트를 참조하십시오. – MKod

답변

2

귀하의 hashCodeObject::hashCode 계약을 위반하는 것입니다. 동일한 객체에 대해 동일한 값을 반환해야합니다. Javadoc의에서

: 같은 예를 들어 hashCode를 호출 할 때마다 다른 값을 반환하면

* <li>Whenever it is invoked on the same object more than once during 
*  an execution of a Java application, the <tt>hashCode</tt> method 
*  must consistently return the same integer, provided no information 
*  used in <tt>equals</tt> comparisons on the object is modified. 
*  This integer need not remain consistent from one execution of an 
*  application to another execution of the same application. 

, 당신은 당신의 HashMap이 키의 위치를 ​​기대할 수 없다.

당신이 ISBN에 따라 해시 코드를 원한다면, 단지 ISBN의 해시 코드를 반환 :

@Override 
public int hashCode() 
{ 
    return this.isbn.hashCode(); 
} 

당신은 또한 당신의 equals 방법을 수정해야합니다, 둘다 말한 외에도

public boolean equals(Object o) 
{ 
    if(o instanceof BookMe && ((BookMe)o).getIsbnValue().equals(this.getIsbnValue())) 
    { 
     return true; 
    } 
    else{ 
     return false; 
    } 
} 
+0

시도 하겠지만 같은 문자열 (예 : "Graham")의 hashCode는 내 BookMe 객체에 대해 동일한 반복 hashCode를 제공합니다. – MKod

+0

@MKod 동일한 ISBN에 대한 hashCode는 동일한 값을 제공해야합니다. 그렇지 않으면 HashMap은이 hashCode를 사용하여 BookBe 키를 찾을 수 없습니다. – Eran

+0

@ Eran ... 나는 뭔가를 추가하고 싶다 ... 만약 내가 오버라이드를하지 않는다면 나는 이미 설명한 3 가지 값 모두를 얻고있다. 여기에 내 심각한 논쟁은 모든 풋에 대한 것이거나 해시 코드를 호출 한 다음 키의 고유성을 파악할 것입니다. 그래서, 내가 overiride 또는하지 않는 경우, 그것 (해시 코드 검사) 여전히 고유성을 확인하는 hashcode 방법으로 이동하십시오. 그런 말로하면, 어떻게 3 가지 값을 모두 갖게 되었습니까? (해시 코드 메서드를 재정의하지 않을 때)? – MKod

0

해시 코드는 동일한 객체에 대해서조차도 새로운 해시 코드를 반환합니다. 요소를지도에 올릴 때와 반복 할 때 equals 메서드를 사용하여 두 문자열을 비교해야합니다. 에

((BookMe)o).getIsbnValue() == this.getIsbnValue() 

변경을 :

((BookMe)o).getIsbnValue().equals(this.getIsbnValue()) 
0

귀하의 hashcode 방법은 고장도 equals 방법 당신은 참조하지 값을 기준으로 문자열을 비교한다. 당신은 해시 코드를 생성 할 수 Objects 방법을 사용할 수 있습니다,이

@Override 
public boolean equals(Object o) { 
    return o instanceof BookMe && ((BookMe) o).getIsbnValue().equals(this.getIsbnValue()); 
} 

같은 equals 메소드를 해결할 수 있습니다 그리고 hashcode를 해결하기

@Override 
    public int hashCode() { 
     return Objects.hash(isbn); 
    } 

이 메소드의 오버라이드 (override) 구현을위한 일반적인 계약은 입니다 그들은 동일한 객체의 equals() 메서드와 일치하는 방식으로 동작합니다. 메서드 : 지정된 객체가 동일한 해시를 일관되게보고해야합니다 ( 값이 변경되지 않는 한 새 버전은 더 이상 이 이전 버전과 동일한 것으로 간주되지 않음), 이()와 동일한 두 객체가 동일한 해시 값을보고해야 함을 의미합니다. 해시 값이 서로 다른 Java 구현간에 일관성을 유지할 필요가 없습니다 ( 또는 심지어 동일한 프로그램의 실행 실행간에 차이가 있음). 다른 해시를 갖는 두 개의 동일하지 않은 객체가 매우 바람직하지만 이것은 필수가 아닙니다 (즉 해시 구현 된 함수가 일 필요는 없습니다.