このコード スニペットでは、特定の job_id を持つ返されたジョブが、retain 関数を使用して実行中のジョブの変更可能な HashSet から削除されることを期待していますが、予想されるエントリは削除されていません。以下にいくつかのデバッグ コードとその出力 (はるか下) を示します。これはセットを反復処理して、セット内にテスト要素と等しい要素があることを示しますが、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_id に相当するプレーンテキストにすぎないことです。この問題を再現できるのは、1 つのジョブ アクション タイプ「request_this」のみです。それが異なるタイプの場合、期待される出力が得られます。例:
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)
}
返された出力は、テスト ジョブのハッシュコード (最初の行) のように見えます。セット内のジョブは、job_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 -- Job オブジェクトが完全に不変になり、症状が自然に解決したようにコードを書き直すことになりました。犯人である hashcode/equals 実装に関しては、Job クラスが「ケース クラス」を使用して定義されたことに言及する価値があるかもしれません。