2009-07-02 2 views
10

Java Set <> (또는 해당 키의 경우 <>에 포함 된) 오브젝트가있는 경우, 해당 필드는 (hashCode(), equals(), compareTo() 등을 통해) 신원 또는 관계를 결정하는 데 사용되는 정보는 수집 작업에 대한 명시되지 않은 동작을 일으키지 않고는 변경할 수 없습니까? (편집 : this other question에서 언급으로)Java Set의 오브젝트에 대한 변경 가능 필드

(즉,이 필드는 불변해야하거나, 당신이 컬렉션에서 제거 할 객체를 요구해야하고 다음 다시 삽입, 변경.)

내가 Hibernate Annotations reference guide을 읽었으며 그곳에 HashSet<Toy>이있는 예가 있지만 Toy 클래스에 nameserial이 있으며이 숫자는 변경 가능하며 또한 hashCode() 계산에 사용됩니다 ... 빨간색 깃발이 내 머리와 나는 단지 그것이 그 의미를 이해하고 있는지 확인하고 싶었다.

답변

7

Set에 대한 javadoc에서는

참고 말한다. 개체의 값이 인 경우 집합의 요소가 이고 개체의 값이 인 경우 집합의 동작은 이 지정되지 않습니다. 이 금지 사항의 특수한 경우 은 자체를 요소로 포함하는 집합에 대해 허용되는 이 아님을 나타냅니다.

이것은 단순히 세트에서 변경 가능한 개체를 사용할 수 있음을 의미합니다. 변경 사항이 Set 항목을 찾는 방식에 영향을 미치지 않는지 확인해야합니다. HashSet의 경우 hashCode() 계산에 사용 된 필드를 변경하지 않아도됩니다.

3

맞습니다.지도 항목을 찾는 데 문제가 발생할 수 있습니다. 공식적으로 동작은 정의되어 있지 않으므로 해시 집합에 추가하거나 해시 맵의 키로 추가하면 변경하지 않아야합니다.

1

네, 그렇게하면 문제가 발생할 것입니다. 변경 가능한 개체를 설정 요소로 사용되는 경우는, 세심의주의가 필요합니다

// Given that the Toy class has a mutable field called 'name' which is used 
// in equals() and hashCode(): 
Set<Toy> toys = new HashSet<Toy>(); 
Toy toy = new Toy("Fire engine", ToyType.WHEELED_VEHICLE, Color.RED); 
toys.add(toy); 
System.out.println(toys.contains(toy)); // true 
toy.setName("Fast truck"); 
System.out.println(toys.contains(toy)); // false 
+0

잠깐, 나는 이것이 정말 나쁜 예임을 깨달았다. 나는 여전히 참조를 보유하고 있으므로, 마지막 contains()는 실제로 true를 반환합니다. HashMaps는 다른 문제이지만 3 일간의 주말에는 거의 끝나고 예제를 파헤 치고 싶지 않습니다. –

+0

ㅎ, 돌아올 때 게시 해주세요. –

+0

다시 기다리십시오. HashSet이 HashMap을 백업으로 사용한다는 것을 잊었습니다. HashMap을 사용하면 버킷에있는 요소에 대해 equals()를 검사하기 전에 hashCode를 사용하여 버킷으로 건너 뛰고 요소를 변경하면 잘못된 버킷으로 건너 뛰고 요소를 찾을 수 없습니다. –

0

HashSet/HashMap에서 은 포함 된 개체를 변경하여 compareTo() 작업의 결과를 변경할 수 있습니다. 상대 비교는 개체를 찾는 데 사용되지 않습니다. 그러나 그것은 TreeSet/TreeMap 내부에서 치명적입니다.

또한 IdentityHashMap 내부에있는 객체를 변형 할 수 있습니다. 객체 ID를 사용하여 내용을 찾는 데 사용할 수있는 것은 없습니다.

이러한 자격으로 이러한 작업을 수행 할 수는 있어도 코드가 더 취약합니다. 누군가가 나중에 TreeSet으로 변경하거나 해시 코드/동등성 테스트에 해당 변경 가능 필드를 추가하려는 경우 어떻게해야합니까?

관련 문제