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