关联数组与 SplObjectStorage
Posted
技术标签:
【中文标题】关联数组与 SplObjectStorage【英文标题】:Associative Array versus SplObjectStorage 【发布时间】:2012-01-21 03:47:17 【问题描述】:我正在编写代码来管理一组独特的对象。这段代码的第一个原型使用了一个关联数组,基本上我一直都是这样做的。
但是,我也热衷于利用已添加到更现代 php 版本中的功能(例如 [SplObjectStorage][1]
'已经看到建议SplObjectStorage
在很多情况下可以比数组更快)。
当前的实现有一个关联数组,我用in_array()
检查一个对象是否已经在数组中,然后再添加一个新对象。
我可以看到SplObjectStorage
的一个大问题是它似乎(乍一看)不支持键/值关联数组行为,并且只能被视为索引数组。但是,PHP 新功能的文档不符合该语言更成熟部分的文档标准,我可能只是遗漏了一些东西。
我可以使用SplObjectStorage
代替关联数组吗?如果是这样,添加新对象时如何定义键?更重要的是,与关联数组相比,SplObjectStorage
的相对优缺点是什么?
【问题讨论】:
SplObjectStorage doesn't work with String, what to do? 的可能重复项 @ajreal:我不认为我的问题和你说的那么相似。 仔细看了看,但仍然看不到我的问题(您可以使用 SplObjectStorage 代替 associative 数组吗?如果可以,有什么好处和缺点? ) 是那个的副本(为什么我不能将字符串放在 SplObjectStorage 中?) 我认为问题已经表明如果你想做关联数组,然后使用 spl 对象哈希,并附加到 spl 存储对象。退税?很麻烦。 spl存储对象的好处是因为使用了索引键(参见实现只使用next,prev来推进指针)。而放回关联键只是违背了目的。这就是我的想法。 【参考方案1】:您不应该将SplObjectStorage
视为键值存储,而只是一组对象。某些东西是否在集合中,但它的位置并不重要。
SplObjectStorage
中元素的“键”实际上是对象的哈希值。这使得无法将同一对象实例的多个副本添加到SplObjectStorage
,因此您不必在添加之前检查副本是否已经存在。
然而,在PHP 5.4
中有一个名为getHash()
的新方法,您可以覆盖该方法将返回对象的“哈希”。这 - 在某种意义上 - 返回/设置密钥,以便您可以允许它在不同的条件下存储。
SplObjectStorage
的主要优势在于,您可以获得许多处理和交互不同集合的方法(contains()
、removeAll()
、removeAllExcept()
等)。它的速度略好,但内存使用率比普通 PHP 数组差。
【讨论】:
在我的实验中,splObjectStorage 实际上使用的内存比一组存储对象哈希的数组要少。 我实际上进行了速度测试,已在此处发布:technosophos.com/content/php-splobjectstorage-v-arrays-redux SPLObjectStorage 似乎有大约 10,000 个 DOMDocuments 的甜蜜点,之后性能下降。【参考方案2】:当分配给数组的所有内存都用完后,分配给它的内存将翻倍。在这种情况下,对象的集合可能是更有效的结构。
【讨论】:
【参考方案3】:在PHP 5.6.13
上运行 benchmark 10000 次迭代后的结果:
Type | Time to fill | Time to check | Memory |
---|---|---|---|
SplObjectStorage | 0.021285057068 | 0.019490000000 | 2131984 |
Array | 0.021125078201 | 0.020912000000 | 1411440 |
如您所见,Array
没有明显比SplObjectStorage
快,但使用减少了 34 % 的内存。
【讨论】:
时间差只有3%,不是50%? 34% 而不是 50% 与内存有关。 @roman 你能在这里解释一下你的数学吗?我的意思是你到达的 1.5。 根据您的数据,我得到数组的填充时间快 1%,检查时间慢 7%,内存使用量减少 34%。 很高兴看到 PHP7 中的统计数据。 @twity1337 因此,在 PHP 7 实例上运行链接中提供的代码。以上是关于关联数组与 SplObjectStorage的主要内容,如果未能解决你的问题,请参考以下文章