Scala 中 Set 去重与样例类

53 阅读2分钟

一、问题引入:自定义类存入 Set 为何无法去重?

先看一个基础案例:定义一个Book类,创建两个 “内容相同” 的Book对象,存入可变 Set 中,观察结果:

package caseclass1

// 导入mutable包下的Set(也可使用通配符import scala.collection.mutable._)
import scala.collection.mutable.Set

object CaseClass {
  class Book(var id: Int, var name: String) {

    override def equals(obj: Any): Boolean = obj match {
      case other: Book => other.id == this.id && other.name == this.name
      case _ => false // 非Book类型直接返回false
    }


    override def hashCode(): Int = id.hashCode() + name.hashCode()
  }

  def main(args: Array[String]): Unit = {

    val set1 = Set(1, 2)
    set1 += 1
    set1 += 1
    set1 += 1
    set1 += 1
    println("set1内容:" + set1)
    val book1 = new Book(1, "西游记")
    val book2 = new Book(1, "西游记")

    println("book1 == book2?" + (book1 == book2))

    // 类型修正:book → Book(类名首字母大写)
    val set2: Set[Book] = Set()
    set2 += book1
    set2 += book2
    println("set2大小:" + set2.size)
  }
}

二、手动实现 equals 和 hashCode 解决去重

要让 Set 根据Book的内容去重,需手动重写equalshashCode方法:

package caseclass1

// 导入mutable包下的Set(也可使用通配符import scala.collection.mutable._)
import scala.collection.mutable.Set

object caseClass {
  class Book(var id: Int, var name: String) {

  }

  def main(args: Array[String]): Unit = {

    val book1 = new Book(1, "西游记")
    val book2 = new Book(1, "西游记")

    println("book1 == book2?" + (book1 == book2))

    // 类型修正:book → Book(类名首字母大写)
    val set2: Set[Book] = Set()
    set2 += book1
    set2 += book2
    println("set2大小:" + set2.size)
  }
}

三、Scala 样例类(Case Class):自动实现相等性判断

手动重写equalshashCode虽能解决问题,但代码冗余。Scala 提供样例类(Case Class)  ,自动为我们实现这些方法,还附带其他便捷特性:

package caseclass1

/* case class 样板类
可以省略 new
属性默认不可变的 val修饰
它会自动去实现toString equlas hascode等方法
 */

object caseclass3 {
  case class Student (name:String, age:Int)

  def main(args: Array[String]): Unit = {
//val st1 = new Student("小花" 18)
//可以省略 new
    val st1 = Student("小花" ,18)
    val st2 = Student("小花" ,18)
    println(st1)
    println(st1 == st2)

  }
}