我正在使用Dictionary,其中键是Number个对象,但如果键是大整数,我会遇到意外问题。
下面是一些在Dictionary中插入两个键值对的示例代码,一个键有一个小键,另一个键有一个大键:
var dictionary:Dictionary = new Dictionary();
var smallNumberKey:Number = 1;
dictionary[smallNumberKey] = "some value";
var largeNumberKey:Number = 0x10000000;
dictionary[largeNumberKey] = "some value";
for (var key:Object in dictionary) {
trace("Key: " + key);
trace("Key type: " + flash.utils.getQualifiedClassName(key));
trace("Key as Number: " + (key as Number));
}
这给出了以下输出:
Key: 1
Key type: int
Key as Number: 1
Key: 268435456
Key type: String
Key as Number: null
没有任何键似乎存储为数字。这是为什么?第一个存储为int,可以转换为Number。然而,第二个似乎存储为字符串,这对我没有意义。这是怎么回事?
答案 0 :(得分:4)
您不能使用Number
作为键,因为二进制浮点数不能很好地用于精确比较,这正是Dictionary
类所做的。 (“使用严格相等(===)进行密钥比较”)。阅读浮点数以了解原因。
因此,当您将Number
指定为Dictionary
的键时,Flash引擎必须将其转换为其他可以准确表示的内容。 String
和int
值都可以完全按其内容表示,因此Flash选择一个将提供的Number
转换为。做一些实验,似乎flash 总是将整数值(即使作为字符串提供)转换为int
,如果小于或等于0xFFFFFFF,并始终转换为{{ 1}}任何大于此的整数,可能是由于一些内部优化以最快的方式比较键:
String
打印:
import flash.utils.Dictionary;
import flash.utils.getQualifiedClassName;
var dictionary:Dictionary = new Dictionary();
var stringKey:String = "123456789";
var intKey:int = 0xFFFFFFF;
var intKey2:int = intKey + 1;
dictionary[stringKey] = "Value 1";
dictionary[intKey] = "Value 2";
dictionary[intKey2] = "Value 3";
for (var key:Object in dictionary) {
trace( key + " [" + getQualifiedClassName(key) + "] = " + dictionary[key]);
}
答案 1 :(得分:1)
来自Adobe doc:
Dictionary类允许您创建动态的属性集合,它使用严格相等(===)进行键比较。当一个对象用作键时,该对象的标识用于查找该对象,而不是从其上调用toString()返回的值。
“使用对象的标识”表示对对象使用引用,指向存储实际对象的内存中的位置的指针。使用原始值作为字典键时的问题是它们永远不会通过引用传递,因此值不会存储在实际字典中(即它们不是引用到对象),而是处理作为“常规”动态属性,就像您期望从Object
那样。当你设置
object[key] = "some value";
键值会自动转换为int
(就像Array
的索引)或String
。
您可以通过使用简单的Dictionary
包装类来解决此问题,和使用NumberKey
的实际性能优势:
package
{
import flash.display.Sprite;
import flash.utils.Dictionary;
public class SimpleTest extends Sprite
{
var dictionary:Dictionary = new Dictionary();
public function SimpleTest() {
var smallNumberKey:NumberKey = new NumberKey(1);
dictionary[smallNumberKey] = "some value";
var largeNumberKey:NumberKey = new NumberKey(0x10000000);
dictionary[largeNumberKey] = "some value";
for(var key:Object in dictionary) {
trace( "Key: "+key );
trace( "Key type: "+flash.utils.getQualifiedClassName( key ) );
trace( "Key as Number: "+(key.numberValue) );
}
}
}
}
package {
public class NumberKey {
public var numberValue : Number;
public function NumberKey( n:Number ) {
numberValue = n;
}
}
}