2013-10-18 3 views
1

보유하고있는 작업의 가변 HashSet에서 주어진 job_id로 반환 된 작업이 retain 함수를 사용하여 반환되기를 기대하고 있지만 예상되는 항목이 제거되지 않는 코드 스 니펫이 있습니다. 아래에 몇 가지 디버그 코드와 그 출력을 (아래) 테스트 요소와 동일한 집합에있는 요소가 있음을 보여주기 위해 집합을 통해 반복하지만 그 설정 크기가 유지 기능을 사용할 때 변경되지 않습니다 해당 작업 ID와 다른 요소를 보유하십시오.예기치 않은 HashSet.retain 동작

if(action=="request_this") { 
    println("RS >%d<\n".format(job.job_id)) 
    for(j <- jobs_running) println(">%d< ".format(j.job_id) + (if(j.job_id==job.job_id) "true" else "false")) 
} 

val c1 = jobs_running.size 
jobs_running.retain(x => x.job_id!=job.job_id) 
println(action+" NET CHANGE %d".format(jobs_running.size-c1)) 

출력 :

이 더욱 수수께끼 나에게 디버그 코드에서 참조 "작업"var에 복귀 작업 개체의 action_id에 그냥 일반 텍스트 해당하는 점이다 만드는 것
RS >1259< 

>1055< false 
>1019< false 
>1051< false 
>1083< false 
>1015< false 
>1215< false 
>1127< false 
>1259< true 
>1107< false 
>1047< false 
>1035< false 
request_this NET CHANGE 0 

. 이 문제를 재현 할 수있는 것은 하나의 작업 유형 "request_this"에만 해당됩니다. 그 다음 다른 유형의 경우 내가 예상 출력 예를 얻을 :

request_that NET CHANGE -1 

UPDATE - 일반적인 합의가 해시 코드와 관련된 일 것으로 보인다. 작업 객체와 job_id 값 모두에 대해 해시 코드를 출력하도록 디버그 코드를 수정했습니다.

if(action=="request_screenshot") { 
    println(">>%d< ".format(job.job_id) + job.hashCode + " " + job.job_id.hashCode+"\n") 
    for(j <- jobs_running) println(">%d< ".format(j.job_id) + j.hashCode + " " + j.job_id.hashCode) 
} 

내가 돌아 왔을 출력은 작업 ID 값과 전체 작업 개체 모두에 대한 설정 경기에서 테스트 작업 (첫 번째 줄)의 해시 코드 및 작업처럼 보인다 (나는 일치에 * 옆에 넣어 세트 요소 출력) :

>>1267< 1619488678 1267 

>1015< 2124747326 1015 
>1043< -183172091 1043 
>1107< -353858330 1107 
>1123< -1258875190 1123 
>963< 1958632623 963 
>1039< 226958301 1039 
>1023< 148063445 1023 
>1215< -972672885 1215 
>959< 283572883 959 
>971< -2080242470 971 
>1091< -1549619606 1091 
>1019< -529588663 1019 
>1047< -552719093 1047 
>967< 626939580 967 
>1035< 1782547037 1035 
>1263< -874427822 1263 
>1027< -228877131 1027 
>1031< 441847990 1031 
*>1267< 1619488678 1267 
>1211< -1435736028 1211 
>1191< 48617136 1191 
>1119< -1737229053 1119 
>1011< 1056625401 1011 
>1127< -1547902819 1127 
>1251< -358437524 1251 

UPDATE2 - 나는 작업 개체가 완전히 불변이고 증상 자체를 해결 한 것 같다 그래서 난 아직도 내가 정확히 무슨 일이 일어 났는지 이해하고자하지만, 내 코드를 재 작성 결국 . hashcode/implals가 범인 인 것과 관련하여 Job 클래스가 "case 클래스"를 사용하여 정의되었다는 것을 언급 할 가치가 있습니다.

+3

set 요소의 'equals'및 'hashCode'를 잘못 구현하면 이와 같은 문제가 발생할 수 있습니다. – ghik

+1

"테스트 요소와 동일한 집합에 요소가 있음을 보여 주도록 설정"은 "다른 것처럼 보임"또는 "obj1.equals (obj2)"와 같음을 묻습니다. – pedrofurla

답변

2

두 질문 :

  1. hashCode의 구현이 requirements에 따라합니까? 아마도 당신은 그들의 구현을 제공 할 수 있습니다.

  2. hashCode이 사용하는 필드는 세트에 삽입 된 후에 변경 불가능하거나 그렇지 않으면 변경되지 않습니까?

편집

세 번째 질문 :

  1. 이, 오른쪽 HashSet 아닌 SortedSet입니까? SortedSet에서 Ordering 구현에 대해서도 걱정할 필요가 있습니다.
+1

역시 'equals' 메소드입니다. 그렇지 않습니까? – pedrofurla

+1

@pedrofurla 출력 결과에 따르면 'equals'는 일부 요소에 대해 true를 반환하므로 좋은 구현이 아니더라도 무언가를 제거해야합니다. –

+0

job_id 값은 변경할 수 없습니다. 그러나 전체 Job 개체의 다른 값은 변경할 수 있습니다. 내가 그것에 대해 생각하고있는 방식은 Int 데이터 유형이 refs가 아니며 job_id가 비교되는 유일한 값이므로 hashCode가 일치를 반환해야한다고 생각합니다. 그게 맞습니까? 아니면 제가 오해하고 있습니까? –