2012-12-10 4 views
4

이 질문은 분명히 새로운 질문이 아니지만 어디에서나 유용한 답변을 찾지 못했습니다.Hashset에서 중복을 허용합니까?

아래 코드에서 볼 수 있듯이 equals 및 hashcode 메서드는 재정의되지만 여전히 중복을 허용합니다. Hashcode는 Netbeans에 의해 자동으로 생성되었습니다.

@Override 
public boolean equals(Object o) 
{ 
    TaskDetails other = (TaskDetails) o; 
    if ((id_subtask == other.id_subtask) 
      && ((date.compareTo(other.date)) == 0)) 
    { 
     System.err.println("Duplicate Entry"+id_subtask+" + "+other.id_subtask); 
     return true; 
    } 
    else 
    { 
     System.out.println("Good!" +id_subtask+" + "+other.id_subtask); 
     return false; 
    } 

} 

@Override 
public int hashCode() { 
    int hash = 7; 
    hash = 71 * hash + this.id_subtask; 
    hash = 71 * hash + this.id_team_member; 
    hash = 71 * hash + Float.floatToIntBits(this.nb_hours); 
    hash = 71 * hash + (this.date != null ? this.date.hashCode() : 0); 
    hash = 71 * hash + (this.comment != null ? this.comment.hashCode() : 0); 
    hash = 71 * hash + (this.subtask_name != null ? this.subtask_name.hashCode() : 0); 
    System.out.println("Hash : "+hash + "Subtask : " + id_subtask); 
    return hash;  
} 

이것은 HashSet의에 항목에 추가하는 데 사용되는 코드 :이 코드 기능 (A)에 사용되는

TaskDetails newTaskDetails = new TaskDetails 
           (
            s.getId_subtask(), 
            mus.teamMember.getId_team_member(), 
            f, 
            mysqlFormat.format(caldate), 
            c.substring(0, Math.min(c.length(), 100)), 
            s.getName_subtask() 
           ); 

          allTasks.add(newTaskDetails); 

(allTasks가 HashSet의 인) 및 B.

을 함수 A 만 실행하면 정상적으로 작동합니다. 함수 B가 함수 A 다음에 실행되면 (위의 코드가 두 번 실행되므로) 중복 항목이 있다고 말하는 system.err가 발생하더라도 해시 세트는 갑자기 중복을 허용합니까?

코드에 결함이 있습니까? 아니면 방금 누락 되었습니까?

도움 주셔서 감사합니다.

+0

나는 hashvalue가 변경되어 newTaskDetails를 조작하는 것으로 의심됩니다. – kosa

+0

당신은 그 클래스를 대체하고 있습니까? –

+1

"중복 허용"이란 정확하게 무엇을 의미합니까? 전체 객체가 같은가, 아니면 중복 된 ID를 의미 하는가? – Zutty

답변

7

2 개의 필드를 사용하여 2 개의 개체를 "같음"으로 간주하지만 2 개 이상의 필드를 사용하여 해시 코드를 구성합니다. 귀하의 hashCode() 방법 equals() 방법보다 구체적일 수 없습니다. 좋은 경험 법칙으로, hashCode() 메서드는 equals() 메서드가 사용하지 않는 필드를 사용해서는 안됩니다 (적은 수만 사용할 수 있음). 좀 더 기술적으로 말하자면 2 개의 객체가 "같음"이라면 이 같은 해시 코드를 가져야합니다 (반대는 필요하지 않음).

+0

감사합니다 jtahlborn 및 Jochen! 그것은 지금 당장 작동하는 것 같습니다! 아마도 일부 개체의 해시 코드가 같은 이유 일 수 있습니다. – Xaviraan

0

이것은 중복 질문입니다. 내 previous answer을 참조하십시오.

java.util.HashSet에있는 개체의 해시 코드가 변경 될 수있는 경우 java.util.HashSet에서 중복을 허용하는 동작이 발생합니다.

이것은 일반적으로 개체의 해시 코드가 변경 가능한 필드로 구성 될 때 발생합니다.

3

hashCode()와 equals() 사이의 일관성 요구 사항을 위반합니다. equals()에 따라 두 객체가 같으면 해시도 동일해야합니다. 당신의 equals는 두 개의 필드만을 고려하고 hashCode는 더 많은 것을 고려하므로이 요구 사항은 충족되지 않습니다.

0

hashCode()의 구현이 equals()과 일치하지 않습니다. 두 가지 방법 모두 은 객체의 동일한 속성을 사용해야합니다 ().

equals()true으로 평가 되더라도 hashCode()이 다른 경우가 많습니다. 이 경우 (다른 hashCode 초) HashMap의 개체가 다릅니다.

동일한 속성을 사용하도록 구현을 수정하십시오. 그런 다음 오류가 사라집니다.javadoc of Object

If two objects are equal according to the equals(Object) method, then 
calling the hashCode method on each of the two objects must produce the 
same integer result. 

귀하의 해시 코드에서

0

equals(Object) 방법에 따라 동일한 두 개체에 대해 서로 다른, 그래서 다른 코드 HashSet 잘못된 가정을하고, 잘못된 결과를 반환 할 것입니다.

일부 코드는 "계약서"를 준수하는 다른 객체에 의존하는 방식으로 작성됩니다. 수업에서는 Object 계약을 준수하지 않으므로 컬렉션에서 Object 계약을 위반하지 않아야하므로 컬렉션의 어떤 것도 작동하지 않는다고 가정 할 수 있습니다.

관련 문제