Scala: why does the mutable Map and the immutable Map have a different result in the same instance of the user class as the key?

My version is Scala 2.11.8, and the Java version is 1.8.0_77.

I had a custom Vextends class Ordered[V]. I defined custom compareand equals. I want copies Vhad >, <, >=, <=operators, and can be considered equal when their specific attribute set.

Here is the simplified code extracted from my project:

class V(val value: Int, val score: Int = 0) extends Ordered[V] {
  def compare(that: V): Int = this.score compare that.score

  override def equals(that: Any): Boolean = that match {
    case that: V => this.value == that.value
    case _ => false
  }
}

val a = new V(1, 2)
val b = new V(1, 3)

// return true because a.value == b.value
a == b

And it’s strange:

import collection.mutable.ArrayBuffer

val mm = collection.mutable.Map(a -> ArrayBuffer(0, 1), b -> ArrayBuffer(2, 3, 4))
val im = collection.immutable.Map(a -> ArrayBuffer(0, 1), b -> ArrayBuffer(2, 3, 4))

// return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
mm.getOrElse(new V(1, 0), ArrayBuffer())

// return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4)
im.getOrElse(new V(1, 0), ArrayBuffer())

Why the result immutable.Mapand mutable.Mapdifferent?

But when I define hashCodefor V:

class V(val value: Int, val score: Int = 0) extends Ordered[V] {
  def compare(that: V): Int = this.score compare that.score

  override def hashCode: Int = value // new method here!

  override def equals(that: Any): Boolean = that match {
    case that: V => this.value == that.value
    case _ => false
  }
}

val a = new V(1, 2)
val b = new V(1, 3)

a == b // true

And this time the result will be the same:

val mm = collection.mutable.Map(a -> ArrayBuffer(0, 1), b -> ArrayBuffer(2, 3, 4))
val im = collection.immutable.Map(a -> ArrayBuffer(0, 1), b -> ArrayBuffer(2, 3, 4))

// both return scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4)
mm.getOrElse(new V(1, 0), ArrayBuffer())
im.getOrElse(new V(1, 0), ArrayBuffer())

hashCode ?

+4
1

hashCode

immutable.Map 4 (Map1,...., Map4). get -, , , - .

, Map1.get, getOrElse:

class Map1[A, +B](key1: A, value1: B) extends AbstractMap[A, B] 
                                      with Map[A, B] with Serializable {
    def get(key: A): Option[B] =
      if (key == key1) Some(value1) else None

, mutable.Map mutable.HashMap, - , , , . -. hashcode, hashcode Any (Object). , , -.

hashcode, , -, HashMap , , equals , , .

+5

Source: https://habr.com/ru/post/1651638/


All Articles