【问题标题】:Checking if a Map contains a key of class type in Scala在 Scala 中检查 Map 是否包含类类型的键
【发布时间】:2021-10-21 02:48:51
【问题描述】:

我是 Scala 的新手,有些事情我很难弄清楚。 我有以下方法:

def updateSongCount(song : Song) {
   if(this.listeningCountMap.contains(song)) {
     this.listeningCountMap(song) += 1
   } 
   else 
   {
     this.listeningCountMap += (song -> 1)
   }
  }

listeningCountMap 是这样定义的:

var listeningCountMap = Map[Song, Int]()

现在,Song 是一个类类型,它有几个参数(如标题、歌手等)。 当我执行包含时,即使两首歌曲之间的所有参数都相同 - 它也会将它们添加为两个单独的条目。 我来自 C#,我习惯于重写 GetHashCode 和 Equals 以便包含了解我的类的两个实例何时被认为是相等的,我想我缺少的是 scala 中的等价物。你能告诉我我们如何在 Scala 中做到这一点吗? 谢谢!

【问题讨论】:

    标签: scala dictionary collections contains


    【解决方案1】:

    如果Song 定义为case class,则编译器使用主构造函数参数生成equals 和hashCode 方法:

    case class Song(id: Int, title: String)
    

    在此示例中,等于和 hashCode 考虑了 idtitle 字段。

    如果您不需要使用所有字段进行比较,您可以重写 equals/hashCode 方法:

    case class Song(id: Int, title: String) {
      override def hashCode() = title.hashCode()
    
      override def equals(obj: Any) = title.equals(if (obj != null) obj.asInstanceOf[Song].title else null)
    }
    

    【讨论】:

    • 酷,我明白了,它奏效了,非常感谢!但是,如果我想在中间定义一些东西——比如我只想通过一两个参数来比较它——比如只通过字段标题进行比较——我该怎么做?
    • @Shirli 有一个带有自定义 equalshashCode 的案例类是一种不好的做法,您可以将其分解为两个不同的案例类,其中一个包含另一个。此外,您在学习语言时应该远离可变性,您可能想看看 Scaladoc 以找到像 Map.emptymap.updatedWith 这样可以帮助您减少样板和更具声明性。 - 无论如何,如果您想跟进更多问题,请随时通过官方Discord server 来。
    • 顺便说一句,Bondarenko,你的答案是错误的。 equals 没有返回布尔值,您缺少 canEquals,这可能会导致一些奇怪的错误。这是我们没有自己定义这些方法的主要原因,它们很难正确。
    • 如果你是case class Song(title: String)(id: Int),那么你不需要像那样覆盖equalshashCode
    • 非常感谢大家! @LuisMiguelMejíaSuárez 我会研究您推荐的平台。我想我在习惯和实际使用 Scala 之间缺乏一些基本的区别,所以我会先尝试学习..
    猜你喜欢
    • 2021-07-11
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2020-11-19
    • 2020-11-17
    • 1970-01-01
    相关资源
    最近更新 更多