目前我有一个名为Collection
的PHP类。它使用数组来保存一组唯一对象。它们是唯一的,不是因为它们有不同的内存地址(尽管很明显它们确实如此),但是在集合中没有等效的对象。
我一直在阅读SplObjectStorage
,它比数组具有明显的速度优势,并且可能比我的Collection
类更容易维护。我的问题是SplObjectStorage
并不关心等同性,只关注身份。例如:
class Foo {
public $id;
function __construct($int){
$this->id=$int;
}
function equals(self $obj){
return $this->id==$obj->id;
}
}
$f1a = new Foo(1);
$f1b = new Foo(1);//equivalent to $f1a
$f2a = new Foo(2);
$f2b = $f2a; //identical to $f2a
$s=new SplObjectStorage;
$s->attach($f1a);
$s->attach($f1b);//attaches (I don't want this)
$s->attach($f2a);
$s->attach($f2b);//does not attach (I want this)
foreach($s as $o) echo $o->id; //1 1 2, but I wish it would be 1 2
所以我一直在考虑如何子类化SplObjectStorage
,以使其attach()
受到对象等效性的限制,但到目前为止,它涉及将对象的$data
设置为“等价签名“似乎需要循环遍历数据结构,直到找到(或不找到)匹配值。
e.g:
class MyFooStorage extends SplObjectStorage {
function attach(Foo $obj){
$es=$obj->id;
foreach($this as $o=>$data) {//this is the inefficient bit
if($es==$data) return;
}
parent::attach($obj);
$this[$obj]=$es;
}
}
有更好的方法吗?
答案 0 :(得分:3)
如果唯一定义相等的东西是相对于另一个对象,那么我担心你想要的东西是不可能的。想一想,除非我检查每个对象,否则无法确定对象是否已包含在数组中,因此无论如何我都会有O(n)的复杂性。
但是,如果你使等式绝对,那么这是可能的。为此,您必须为每个对象生成哈希值。当且仅当它们的哈希相等时,两个对象才是相等的。一旦你有了,那么你可以使用HashMap实现O(1)。
通过将对象的地址作为其哈希值,这正是SplObjectStorage所做的事情。