문제

이 버그는 찾는 데 시간이 걸렸습니다 ...

이 방법을 고려하십시오.

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    set.remove(obj)
}

비어 있지 않은 해시 세트로 메소드를 호출하지만 요소는 제거되지 않습니다!

왜 그게 될까요?

도움이 되었습니까?

해결책

해시 세트의 경우 객체의 해시 코드가 세트에 추가 된 후 변경된 경우 발생할 수 있습니다. Hashset.remove () 메소드는 잘못된 해시 버킷을보고 찾지 못할 수 있습니다.

ITERATOR.REMOVE ()를 수행 한 경우에는 발생하지 않을 것이지만 어쨌든 해시 코드가 변경 될 수있는 해시 세트에 객체를 저장하는 것은 (발견 한대로) 발생하기를 기다리는 사고입니다.

다른 팁

퍼즐? 만약에 Object.hashCode, Object.equals 또는 "해시 세트"가 잘못 구현되었습니다 (예 : java.net.URL - 사용 URI).

또한 (직접 또는 간접적으로) 세트에 자체가 포함 된 경우, 이상한 일이 발생할 수 있습니다 (정확히 달의 구현 및 단계 의존).

세트의 구현 유형은 무엇이며 세트 내부에 어떤 개체가 있습니까?

  • 해시 세트 인 경우 객체의 hashcode () 메소드 값이 그 사이에 일정하게 유지되어 있는지 확인하십시오. set.put(...) 그리고 set.remove(...).
  • 트리셋 인 경우 세트의 비교기 또는 물체의 영향에 영향을 미치는 물체에 수정되지 않았는지 확인하십시오. compareTo 방법.

두 경우 모두, 사이의 코드 set.put(...) 그리고 set.remove(...) 각 클래스 구현에 의해 정의 된 계약을 위반합니다. 경험상, 불변의 객체를 설정 컨텐츠 (및지도 키)로 사용하는 것이 좋습니다. 바로 본질적으로 그러한 객체는 세트 안에 저장되는 동안 변경할 수 없습니다.

다른 세트 구현을 사용하는 경우 계약을 위해 Javadoc을 확인하십시오. 그러나 보통 equals 또는 hashCode 객체가 세트에 포함되어있는 동안 동일하게 유지되어야합니다.

실종을 넘어 ';' ~ 후에 set.remove(obj), 그것은 세 가지 상황에서 발생할 수 있습니다 (Javadoc에서 인용).

ClassCastException - if the type of the specified element is incompatible with this set (optional).
NullPointerException - if the specified element is null and this set does not support null elements (optional). 
UnsupportedOperationException - if the remove method is not supported by this set.

당신은 또한 시도 할 수 있습니다 :

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    iterator.remove();
}

그럴 경우 :

public void foo(Set<Object> set)
{
    Iterator i = set.iterator();
    i.next();
    i.remove();
}

?

버그는 다음과 관련이있을 수 있습니다.

공개 void remove ()

반복 이이 방법을 호출하는 것 이외의 다른 방식으로 반복이 진행되는 동안 기본 컬렉션이 수정되면 반복자의 동작이 지정되지 않습니다.

(참조)

나는 도울 수는 없지만 문제는 세트가 참조가 아니라 가치별로 전달된다고 생각한다. 나는 Java에 대한 경험이 많지 않아서 완전히 잘못 될 수 있습니다.

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