2013-10-08 39 views
0

我有一个应用程序在scala.collection.immutable.Map中使用连续查找,使用相同的键,这导致返回两个不同的引用。喜欢的东西下面:Scala不可变映射为同一个键返回不同的值

val v1 = m(key) 
val v2 = m(key) 
require(v1 eq v2) // fails! 

我一直无法重现一个小例子这种行为,我想知道是否有下,这可能是合理的/预期的任何情况。该应用程序是单线程的,我通过查找一个接一个地查找问题来隔离这个问题。

+0

你有并发?你有副作用'hashcode'或'equals'方法吗? – ziggystar

+0

该应用程序是顺序的(没有并发)。 'hashcode'是一个'Int' val'(每个对象都是唯一的),'equals'比较'hashcode'的值。 – zoidbergsky

回答

1

我怀疑你正在测试参考平等。在这种情况下,v1和v2是不同的对象。除非您创建案例类,否则引用相等是类的默认值。

+2

但v1和v2应该是同一个对象。如果他使用'get',那么这将是一个不同的故事(不同的'选项'实例) –

+0

Luigi - 我也希望返回的值是相同的。虽然这些值在'equals'下是等价的,但它们的引用(如'eq'测试的)不是。 – zoidbergsky

1

是否有可能您的地图是不可变的,但您使用的键是可变的或有不正确的hashcodeequals实现返回非确定性结果?你使用的是什么类型?

过分夸张的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 
+0

这些键是可变的(包含'var'字段),但它们在两个'apply'调用之间没有变异。 'hashcode'和'equals'方法是确定性的,它们被实现为仅仅依赖于对象的一个​​'val'字段,并且每个对象具有该字段的唯一值。 – zoidbergsky

相关问题