2011-08-11 2 views
10

신참 질문이해 자바 HashSet에 대한 자바 HashSet의 방법

Set<User> s = new HashSet<User>(); 
User u = new User(); 
u.setName("name1"); 
s.add(u); 
u.setName("name3"); 
System.out.println(s.contains(u)); 

사람이 왜이 코드 출력 거짓 설명 할 수가 들어? 게다가이 코드는 심지어 사용자의 equals 메소드를 호출하지도 않습니다. 그러나 HashSet과 HashMap의 출처에 따르면 그것을 호출해야합니다. 사용자의 메소드 equals는 단순히 사용자 이름에 대해 equals를 호출합니다. 메서드 hashCode 사용자 이름의 hashCode를 반환합니다.

+0

당신이 구현나요 (해시 충돌 반대) 두 항목이 실제로 동일한 있는지 확인, equals를 호출'User.equals()'방법 ? –

+0

Jon Skeet의 인용문 "해시 세트의 오브젝트는 불변이거나, 해시 세트 (또는 해시 맵)에서 사용 된 후에도 변경하지 않으려면 규율을 수행해야합니다." - http://stackoverflow.com/questions/4718009/mutable-objects-and-hashcode – Qwerky

답변

13

해시 코드 방법이 name 필드를 기반으로하고 객체를 추가 한 후이를 변경하면 두 번째 contains 검사가 새 해시 값을 사용하고 찾을 수 없습니다. 네가 찾고 있던 물건. 이는 해시 코드로 HashSet의 첫 번째 검색을 수행하므로 검색이 실패하면 equals으로 전화하지 않아도됩니다. 이 작업을 할

있는 유일한 방법은 당신 하지 무시 equals (그래서 기본 참조 평등 사용) 하고 있던 경우에 당신이 운이있어 두 객체의 해시 코드가 동일했다. 그러나 이는 시나리오 일 수 있으므로 사용하지 마십시오.

일반적으로 은 변경 사항이 해시 코드를 변경하는 경우 HashSet에 추가 한 후에 개체를 업데이트해야합니다.

+0

그래서 해시 세트에 추가 된 u의 복사본이 있습니까? 그렇지 않으면 나는 네임 세트의 객체가 name3을 가질 것이라고 생각한다. – Ced

9

새로운 User에는 다른 해시 코드가 있기 때문에 HashSet은 그것이 동일하지 않다는 것을 알고 있습니다.

HashSet은 해시 코드에 따라 항목을 저장합니다. 이 같은 해시 코드와 아이템을 발견하면
HashSet의 만

+1

실제로 hashCode가 동일한 경우에만 equals가 호출된다. 즉, hashCode를 변경하는 User를 업데이트하면 해당 hashCodes와 연결된 Entry가 들어있는 중첩 배열이 업데이트되지 않습니다. 따라서이 배열을 반복하면 동일한 hashCode를 가진 항목이 반환되지 않습니다. hashCode가 항상 0을 반환하는 경우 작동해야 함) – user12384512

+3

정확함. 일반적으로 HashSet에 변경 가능한 객체를 넣는 것은 나쁜 생각입니다. 'hashCode()'가'0'을 반환하게 만들면 HashSet의 모든 성능상의 이점을 상실하게되고, 아마도 가장 느린 콜렉션으로 끝날 것입니다. – SLaks

+0

나는 이것이 단지 예일 뿐이라는 것을 알고있다. – user12384512