※この記事は仕事用アカウントから個人用アカウントに移行した記事になります。
動機
Collection内のObjectのKeyだけ比較して集合演算したい!みたいなことって割とあると思います。
試してみた
key
とvalue
をもつcase classを定義し、keyの値で集合演算をしたい場合で考えます。
何も考えずにやると以下のようにうまくいきません。
list内の Obj(b,1)
と del内の Obj(b,2)
を同じオブジェクトと判定できず除外してくれません。
case class Obj(key: String, value: Int)
val list = List(
Obj("a", 1),
Obj("b", 2),
Obj("c", 3)
)
val del = List(
Obj("b", 11),
Obj("b", 12),
Obj("d", 13)
)
list diff del // => res0: List[Obj] = List(Obj(a,1), Obj(b,2), Obj(c,3))
直してみた
Obj
の equals
とhashCode
をoverrideしてやればうまくいきます。良かったですね。
(equals内の実装は適当なのでプロダクションに入れるときはinstanceが異なる場合なども考慮してちゃんと実装しましょう)
case class Obj(key: String, value: Int) {
override def equals(arg0: Any): Boolean = {
key == arg0.asInstanceOf[Obj].key
}
override def hashCode(): Int = {
key.hashCode
}
}
val list = List(
Obj("a", 1),
Obj("b", 2),
Obj("c", 3)
)
val del = List(
Obj("b", 11),
Obj("b", 12),
Obj("d", 13)
)
list diff del // => res0: List[Obj] = List(Obj(a,1), Obj(c,3))
説明
Javaオブジェクトの比較には Object#equals
, Object#hashCode
を利用します。
Scalaでも同様にこれらのメソッドを任意に書き換えてあげれば良いようです。
今回は diff
でしか検証してませんが、恐らく他の集合演算メソッドでも同様だと思います。
追記
コメントでご指摘頂いたとおり、case classのequals()
, hashCode()
をoverrideするのは注意が必要です。
特に理由が無ければ別の方法を取るべきだと思います。詳細はコメントを御覧ください。
↑
元記事をアカウントごと消してしまったのでコメントが閲覧できなくなりました。
移行前にコメントだけ引用しておくべきだった・・・。
以上です。