LoginSignup
1
0

More than 5 years have passed since last update.

ScalaでCollection内オブジェクトの任意の条件で集合演算をする

Last updated at Posted at 2018-12-02

※この記事は仕事用アカウントから個人用アカウントに移行した記事になります。

動機

Collection内のObjectのKeyだけ比較して集合演算したい!みたいなことって割とあると思います。

試してみた

keyvalueをもつ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))

直してみた

ObjequalshashCode を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するのは注意が必要です。
特に理由が無ければ別の方法を取るべきだと思います。詳細はコメントを御覧ください。

元記事をアカウントごと消してしまったのでコメントが閲覧できなくなりました。
移行前にコメントだけ引用しておくべきだった・・・。

以上です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0