大数字作为词典中的键(ActionScript 3)

时间:2012-02-25 20:19:14

标签: actionscript-3 dictionary

我正在使用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。然而,第二个似乎存储为字符串,这对我没有意义。这是怎么回事?

2 个答案:

答案 0 :(得分:4)

您不能使用Number作为键,因为二进制浮点数不能很好地用于精确比较,这正是Dictionary类所做的。 (“使用严格相等(===)进行密钥比较”)。阅读浮点数以了解原因。

因此,当您将Number指定为Dictionary的键时,Flash引擎必须将其转换为其他可以准确表示的内容。 Stringint值都可以完全按其内容表示,因此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;
        }
    }
}