2012-02-25 75 views
2

我正在使用Dictionary其中鍵是Number對象,但如果鍵是大整數,則會遇到意外問題。字典中的大數字作爲鍵(動作3)

下面是插入在Dictionary 2鍵 - 值對,其中一個具有小密鑰和一個與一個大的一些示例代碼:

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。但第二個似乎被存儲爲一個字符串,這對我來說沒有意義。這裏發生了什麼?

回答

1

從Adobe的文檔:

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

要非常小心使用這種方法。由於您使用的是對象,因此提供給您的NumberKey的'Number'與密鑰的身份無關,就像'Dictionary'鍵一樣。使用完全相同的數字構造的一百萬個NumberKey對象將創建一百萬個獨特的字典條目。 – 2012-02-26 02:57:41

+0

當然,這是正確的。你需要跟蹤你已經創建的密鑰。不過,這是實際使用詞典的詞典部分的唯一方法。 – weltraumpirat 2012-02-26 17:20:53

4

您不能使用Number作爲重點,因爲二進制浮點點數不適合精確比較,這正是Dictionary類所做的。 (「使用嚴格平等(===)進行密鑰比較」)。閱讀浮點數來理解原因。

因此,當您將Number指定爲Dictionary的關鍵字時,Flash引擎必須將其轉換爲其他可精確表示的東西。 Stringint值都可以用它們的內容精確表示,所以Flash選擇一個將提供的Number轉換爲。做了一些嘗試,似乎閃存總是如果小於或等於0xFFFFFFF,則將整數值(即使作爲字符串提供)轉換爲int,並且總是將轉換爲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]); 
} 

打印:

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

使用原始值作爲鍵將動態屬性添加到字典實例,但它沒有利用Dictionary的優化機制。如果你採用這種方法,你也可以使用一個簡單的對象。 – weltraumpirat 2012-02-26 17:23:00