TreeSet や TreeMap で、重複登録できてしまう

TreeSet 及び TreeMap では同一判定に、equalsメソッドではなくComparator を使用します。そのため、Comparatorの比較の仕様が間違っている場合には意図せぬ重複登録が出来てしまいます。

例えば、オブジェクトのプロパティで以下の3点があったとします。
  • ID(キー)
  • 名前
  • 処理日時
そしてこのオブジェクトをIDの重複を排除して、TreeSet や TreeMapに登録しようとしているとします。このときにComparatorで「ID・名前・処理日時」の3つを順に比較する実装にした場合、IDが同じでも、名前か処理日時のどちらかが異なっていれば、TreeSet や TreeMapに登録できてしまいます。equalsメソッドの実装がどうなっていようと関係なく。

Comparatorの仕様としては、IDの内容が重複した場合に次に名前、その次に処理日時の内容に基づき比較します。つまり、「ID・名前・処理日時」の3つを比較する実装にしているということは、理論的にはIDは重複することが前提でなければなりません。つまり、IDの重複を排除して登録しようとしているにも関わらずキーであるはずのID以外の項目が比較項目になっていること自体がバグといえると思います。

ただ多くの場合は、equalsメソッドで同一判定をしているので、「equalsメソッドをきちんと実装しているのになぜ?」ということは十分におこりうると思います。TreeSet や TreeMap は特別だということを覚えておくことは重要だと思います。