我有这段代码,我希望使用retain函数从正在运行的作业的可变HashSet中删除具有给定job_id的返回作业,但是不会删除预期的条目。我在下面有一些调试代码和它的输出(远远低于),它遍历集合以显示集合中的元素等于测试元素,但是当使用retain函数时,集合大小不会改变保留不等于该职位ID的元素。
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))
输出:
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
让我更加困惑的是,调试代码中引用的“action”var只是与返回作业对象中的action_id等效的明文。它只适用于一个作业动作类型“request_this”,我可以重现这个问题。如果它是一个不同的类型,那么我得到预期的输出ex:
request_that NET CHANGE -1
更新 - 普遍的共识似乎与哈希码有关。我修改了我的调试代码,打印出Job对象和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)
}
我得到的输出看起来像测试作业的哈希码(第一行),并且set中的作业匹配job_id值和整个作业对象(我在匹配的set元素打印输出旁边放了一个*) :
>>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 - 我最终重写了我的代码,以便Job对象完全不可变,症状似乎已经解决了,尽管我仍然希望我明白究竟发生了什么。关于hashcode / equals implimentations是罪魁祸首,可能值得一提的是Job类是使用“case class”定义的。
答案 0 :(得分:2)
两个问题:
hashCode
的实施是否遵循requirements?也许你可以提供他们的实施。
hashCode
使用的字段是不可变的,或者在插入集合后是否会发生变异?
修改强>
第三个问题:
HashSet
,而不是SortedSet
,对吗?在SortedSet
上,您还需要担心Ordering
实施。