【问题标题】:Large Numbers as keys in Dictionaries (ActionScript 3)大数作为字典中的键 (ActionScript 3)
【发布时间】:2012-02-25 20:19:14
【问题描述】:

我正在使用Dictionary,其中键是Number 对象,但如果键是大整数,我会遇到意想不到的问题。

下面是一些示例代码,它在字典中插入两个键值对,一个带有小键,一个带有大键:

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。然而,第二个似乎存储为字符串,这对我来说毫无意义。这是怎么回事?

【问题讨论】:

    标签: actionscript-3 dictionary


    【解决方案1】:

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

    因此,当您将Number 作为键分配给Dictionary 时,Flash 引擎必须将其转换为可以精确表示的其他东西。 Stringint 值都可以由它们的内容精确表示,因此 Flash 选择一个将提供的 Number 转换为。做一些实验,如果小于或等于 0xFFFFFFF,flash 总是 将整数值(即使作为字符串提供)转换为 int,并且总是转换为 String any大于此的整数,可能是由于以最快的方式比较键的一些内部优化:

    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]);
    }
    

    打印:

    123456789 [int] = Value 1
    268435455 [int] = Value 2
    268435456 [String] = Value 3
    

    【讨论】:

    • 使用原始值作为键向字典实例添加动态属性,但它没有利用字典的优化机制。如果您采用这种方法,您不妨使用一个简单的对象。
    【解决方案2】:

    来自 Adob​​e 文档:

    Dictionary 类允许您创建属性的动态集合,该集合使用严格相等 (===) 进行键比较。当一个对象用作键时,该对象的标识用于查找该对象,而不是通过对其调用 toString() 返回的值。

    “使用对象的标识”是指使用对象的引用,一个指向内存中实际对象存储位置的指针。使用原始值作为字典键时的问题是它们永远不会通过引用传递,因此这些值不会存储在实际字典中(即它们不是对象的引用),而是被处理作为“常规”动态属性,就像您对 Object 所期望的一样。当你设置

    object[key] = "some value";
    

    键值会自动转换为int(就像Array 的索引)或String

    您可以通过使用简单的NumberKey 包装类来解决此问题,并且使用Dictionary 的实际性能优势:

    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;
            }
        }
    }
    

    【讨论】:

    • 对这种方法要非常小心。因为您正在使用对象,所以提供给您的NumberKeyNumber 与作为Dictionary 密钥的密钥身份无关。用完全相同的数字构造一百万个NumberKey 对象将创建一百万个唯一的字典条目。
    • 这当然是正确的。您需要跟踪已创建的密钥。但是,这是实际使用 Dictionary 的 Dictionary 部分的唯一方法。
    猜你喜欢
    • 2011-01-24
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    相关资源
    最近更新 更多