我有一个应用程序在scala.collection.immutable.Map中使用连续查找,使用相同的键,这导致返回两个不同的引用。喜欢的东西下面:Scala不可变映射为同一个键返回不同的值
val v1 = m(key)
val v2 = m(key)
require(v1 eq v2) // fails!
我一直无法重现一个小例子这种行为,我想知道是否有下,这可能是合理的/预期的任何情况。该应用程序是单线程的,我通过查找一个接一个地查找问题来隔离这个问题。
我有一个应用程序在scala.collection.immutable.Map中使用连续查找,使用相同的键,这导致返回两个不同的引用。喜欢的东西下面:Scala不可变映射为同一个键返回不同的值
val v1 = m(key)
val v2 = m(key)
require(v1 eq v2) // fails!
我一直无法重现一个小例子这种行为,我想知道是否有下,这可能是合理的/预期的任何情况。该应用程序是单线程的,我通过查找一个接一个地查找问题来隔离这个问题。
我怀疑你正在测试参考平等。在这种情况下,v1和v2是不同的对象。除非您创建案例类,否则引用相等是类的默认值。
但v1和v2应该是同一个对象。如果他使用'get',那么这将是一个不同的故事(不同的'选项'实例) –
Luigi - 我也希望返回的值是相同的。虽然这些值在'equals'下是等价的,但它们的引用(如'eq'测试的)不是。 – zoidbergsky
是否有可能您的地图是不可变的,但您使用的键是可变的或有不正确的hashcode
和equals
实现返回非确定性结果?你使用的是什么类型?
过分夸张的REPL例如:
scala> import scala.util.Random
import scala.util.Random
scala> class BadKey(val value: Int) {
| override def hashCode = Random.nextInt(Int.MaxValue)
|
| override def equals(x: Any) = Random.nextBoolean
| }
defined class BadKey
scala> val randMap = Map(new BadKey(1) -> 1, new BadKey(2) -> 2)
randMap: scala.collection.immutable.Map[BadKey,Int] = Map([email protected] -> 1, [email protected] -> 2)
scala> randMap.get(new BadKey(1))
res6: Option[Int] = Some(1)
scala> randMap.get(new BadKey(1))
res7: Option[Int] = Some(2)
scala> randMap.get(new BadKey(1))
res8: Option[Int] = Some(1)
scala> randMap.get(new BadKey(1))
res9: Option[Int] = Some(1)
scala> randMap.get(new BadKey(1))
res10: Option[Int] = Some(1)
scala> randMap.get(new BadKey(1))
res11: Option[Int] = None
这些键是可变的(包含'var'字段),但它们在两个'apply'调用之间没有变异。 'hashcode'和'equals'方法是确定性的,它们被实现为仅仅依赖于对象的一个'val'字段,并且每个对象具有该字段的唯一值。 – zoidbergsky
你有并发?你有副作用'hashcode'或'equals'方法吗? – ziggystar
该应用程序是顺序的(没有并发)。 'hashcode'是一个'Int' val'(每个对象都是唯一的),'equals'比较'hashcode'的值。 – zoidbergsky