-
Notifications
You must be signed in to change notification settings - Fork 21
java.util.NoSuchElementException: key not found: Constant(NaN) #2598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Imported From: https://issues.scala-lang.org/browse/SI-2598?orig=1 |
@dcaoyuan said: java.util.NoSuchElementException: key not found: MA2
[java] at scala.collection.MapLike$$class.default(MapLike.scala:191)
[java] at scala.collection.mutable.HashMap.default(HashMap.scala:21)
[java] at scala.collection.MapLike$$class.apply(MapLike.scala:106)
[java] at scala.collection.mutable.HashMap.apply(HashMap.scala:21) It seems hash is broken? |
@paulp said: The corner case is that in java NaN != NaN in float primitives, but NaN == NaN among the boxed. Hopefully NaN is the only case where the boxed type has more generous equality than the primitive. |
@paulp said:
Possibly. I'll review the implementation shortly, but at the moment there's some other breakage in trunk so I'll queue up over by the snack bar. |
@dcaoyuan said: Welcome to Scala version 2.8.0.r19480-b20091110111040 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val a = Array(1f)
a: Array[Float] = Array(1.0)
scala> val b = Array(Float.NaN)
b: Array[Float] = Array(NaN)
scala> val c = scala.collection.mutable.ArrayBuffer(1f)
c: scala.collection.mutable.ArrayBuffer[Float] = ArrayBuffer(1.0)
scala> val d = scala.collection.mutable.ArrayBuffer(Float.NaN)
d: scala.collection.mutable.ArrayBuffer[Float] = ArrayBuffer(NaN)
scala> val m = scala.collection.mutable.HashMap(a -> "a", b -> "b", c -> "c", d -> "d")
m: scala.collection.mutable.HashMap[ScalaObject,java.lang.String] = Map([F@62b92956 -> a, ArrayBuffer(1.0) -> c, [F@6a48ffbc -> b, ArrayBuffer(NaN) -> d)
scala> m(a)
res0: java.lang.String = a
scala> m(b)
res1: java.lang.String = b
scala> m(c)
res2: java.lang.String = d
scala> m(d)
java.util.NoSuchElementException: key not found: ArrayBuffer(NaN)
at scala.collection.MapLike$$class.default(MapLike.scala:191)
at scala.collection.mutable.HashMap.default(HashMap.scala:21)
at scala.collection.MapLike$$class.apply(MapLike.scala:106)
at scala.collection.mutable.HashMap.apply(HashMap.scala:21)
at .<init>(<console>:10)
at .<clinit>(<console>)
at RequestResult$$.<init>(<console>:4)
at RequestResult$$.<clinit>(<console>)
at RequestResult$$result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1$$$$anonfun$$apply$$13.apply(Interpreter.scala:788)
at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1$$$$anonfun$$apply$$13.apply(Interpreter.scala:788)
at scala.util.control.Exception$$Catch.apply(Exception.scala:79)
at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1.apply(Interpreter.scala:787)
at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1.apply(Interpreter.scala:787)
at scala.util.control.Exception$$Catch.apply(Exception.scala:79)
at scala.tools.nsc.Interpreter$$Request.loadAndRun(Interpreter.scala:786)
at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:435)
at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:425)
at scala.tools.nsc.InterpreterLoop.interpretStartingWith(InterpreterLoop.scala:331)
at scala.tools.nsc.InterpreterLoop.command(InterpreterLoop.scala:308)
at scala.tools.nsc.InterpreterLoop.processLine$$1(InterpreterLoop.scala:205)
at scala.tools.nsc.InterpreterLoop.repl(InterpreterLoop.scala:223)
at scala.tools.nsc.InterpreterLoop.main(InterpreterLoop.scala:379)
at scala.tools.nsc.MainGenericRunner$$.createLoop$$1(MainGenericRunner.scala:119)
at scala.tools.nsc.MainGenericRunner$$.main(MainGenericRunner.scala:144)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
|
@dcaoyuan said: |
@paulp said:
Fixing this is straightforward (I just did it locally) but it looks like a steep performance price to pay relative to the utility. I'll have to wait and see how martin wants to handle it. |
@adriaanm said: In general, it's not a good idea to use floats as hash keys -- then again, how can the Pickler avoid that problem? |
@odersky said: |
@paulp said: scala> val m = scala.collection.mutable.HashMap(Float.NaN -> "hi")
m: scala.collection.mutable.HashMap[Float,java.lang.String] = Map(NaN -> hi)
scala> m(Float.NaN)
java.util.NoSuchElementException: key not found: NaN
at scala.collection.MapLike$$class.default(MapLike.scala:191) I don't see how it's fixable at the location where you put the nan code, or how to avoid the check in the boxesruntime equals method. That's what I was referring to in comment #5. |
@odersky said: |
@dcaoyuan said: scala> val a= Float.NaN
a: Float = NaN
scala> val b = Float.NaN
b: Float = NaN
scala> a.equals(b)
res0: Boolean = true
scala> Float.NaN equals Float.NaN
res1: Boolean = true And, at least, Float.NaN can be put in HashMap in Java. Float.NaN/Double.NaN is used a lot in scientific computing, since it's the only number that keeps same value (NaN) upon any operations. The problem I see is that when any class/object contains or deeply contains some fields which can be filled with Float.NaN, may suffer from it. |
@odersky said: new java.lang.Float(NaN) != new java.lang.Float(NaN) would be desirable to follow primitive float equality. On the other hand, val x = new java.lang.Float(NaN)
x == x must hold because x eq x. But note that val x = Float.NaN
x == x also must yield false. So it's a paradox which can't be resolved. The only consolation is that NaN is a paradox by itself. The only advice I can give is don't use it, or at least be extremely careful where you use it! -- Martin |
The following code works at least until 2.8.0.r19433, but not now:
I add "final" before a class's val field "a" to prevent overridden
The text was updated successfully, but these errors were encountered: