Actionscript 3 创建一个;“真的”;ActionScript 3中对象相等的HashMap实现

Actionscript 3 创建一个;“真的”;ActionScript 3中对象相等的HashMap实现,actionscript-3,collections,hash,Actionscript 3,Collections,Hash,我花了一些业余时间为ActionScript 3编写了一组集合,但由于ActionScript 3处理字典对象内部的平等性检查的方式,我遇到了一个相当严重的障碍 当您比较字典中的键时,ActionScript使用===运算符来执行比较,这有一点令人讨厌的副作用,即只有对同一实例的引用才能解析true而不是相等的对象。我的意思是: const jonny1 : Person = new Person("jonny", 26); const jonny2 : Person = new Person(

我花了一些业余时间为ActionScript 3编写了一组集合,但由于ActionScript 3处理字典对象内部的平等性检查的方式,我遇到了一个相当严重的障碍

当您比较字典中的键时,ActionScript使用===运算符来执行比较,这有一点令人讨厌的副作用,即只有对同一实例的引用才能解析true而不是相等的对象。我的意思是:

const jonny1 : Person = new Person("jonny", 26);
const jonny2 : Person = new Person("jonny", 26);

const table : Dictionary = new Dictionary();
table[jonny1] = "That's me";

trace(table[jonny1]) // traces: "That's me"
trace(table[jonny2]) // traces: undefined. 
我试图解决这一问题的方法是提供一个均衡器接口,该接口如下所示:

public interface Equalizer 
{
    function equals(object : Object) : Boolean;
}
这允许在需要在集合内执行相等操作时执行instanceOf-esq。检查(当对象未实现均衡器时,返回===运算符);然而,这并不能回避我的底层数据结构(Dictionary对象)对此一无所知的事实

我目前解决这个问题的方法是迭代字典中的所有键,并在执行containsKey()或get()操作时执行相等性检查——然而,这几乎破坏了hashmap的整个点(廉价的查找操作)


如果我无法继续使用字典实例作为映射的备份,我将如何为作为键传入的唯一对象实例创建哈希,以便我仍然可以保持相等?

如何在插入对象时计算对象的哈希代码,然后通过备份字典中的哈希代码进行查找?hashcode应该比较===很好。当然,这需要为对象类型提供一个哈希接口,而不是均衡器接口,因此它的工作量不会比您现在所做的少很多,但您确实可以获得廉价的查找。

不如这样做:

 public interface Hashable {
      function hash():String;
 }
就我个人而言,我问自己,你为什么要这么做。。。如果对象是可变的,则哈希对象以获取密钥没有什么意义

也可以考虑使用不同的方法,例如这个工厂:

package {
 public class Person {
  /**
   * don't use this!
   * @private
   */
  public function Person(name:String, age:int) {
   if (!instantiationAllowed)
    throw new Error("use Person.getPerson instead of constructor");
   //...
  }
  private static var instantiationAllowed:Boolean = false;
  private static var map:Object = {};
  private static function create(name:String, age:int):Person {
   instantiationAllowed = true;
   var ret:Person = new Person(name, age);
   instantiationAllowed = false;
  }
  public static function getPerson(name:String, age:int):Person {
   var ageMap:Array = map[name];
   if (ageMap == null) {
    map[name] = ageMap = [];
    return ageMap[age] = Person.create(name, age);
   }
   if (ageMap.hasOwnProperty(age))
    return ageMap[age];
   return ageMap[age] = Person.create(name, age);
  }
 }
}

它确保了在任何编程语言中,只有一个人具有给定的姓名和年龄(如果有意义的话).

const jonny1 : Person = new Person("jonny", 26);
const jonny2 : Person = new Person("jonny", 26);

正在创建两个完全不同的对象,它们不会使用==进行比较,我想我不明白为什么它会成为一个障碍,因为我知道as3的旧线程,但仍然值得发布

const jonny1:Person=新人(“jonny”,26);const jonny2:Person=新人(“jonny”,26)

正在创建两个完全不同的对象,它们不会使用==进行比较,我想我不明白为什么它会因为as3而成为一个障碍

AS3/JavaScript/EcmaScript的问题不在于它们创建了两个不同的等效对象

问题是它们不能将这两个等价的对象等同起来——只有identity起作用,因为没有equals或hashCode方法可以用特定于类的比较逻辑重写

对于动态对象或字典等映射实现,这意味着您必须使用字符串或引用作为键:您无法使用不同但等效的对象从映射中恢复对象

为了解决这个问题,人们要么求助于严格的toString实现(对于对象映射),这是不可取的,要么求助于字典的实例控制,如@back2dos示例,它引入了不同的问题(另外,请注意,@back2dos解决方案并不能真正保证唯一的Person实例,因为存在允许异步线程实例化新Person的时间窗口)

@A.Levy的解决方案是好的,只是一般来说,hashcode并不严格要求发出唯一的值(它们旨在将条目映射到bucket,以便快速查找,其中细粒度的区分是通过equals方法完成的)

您需要一个hashCode和一个equals方法,例如

public interface IEquable
{
    function equals(object : Object) : Boolean;
    function hash():String;    
}