随着 TDictionary 的不断增长,如何避免内存不足?
TDictionary
使用一个内部数组,如果已满则加倍:
newCap := Length(FItems) * 2;
if newCap = 0 then
newCap := 4;
Rehash(newCap);
这对于中等数量的项目表现良好,但如果达到上限,则非常不幸,因为它可能即使还有近一半的内存仍然可用,也会抛出 EOutOfMemory
异常。
有什么办法可以影响这种行为吗?其他集合类如何处理这种情况?
TDictionary<TKey,TValue>
uses an internal array that is doubled if it is full:
newCap := Length(FItems) * 2;
if newCap = 0 then
newCap := 4;
Rehash(newCap);
This performs well with medium number of items, but if one gets to the upper limit it is very unfortunate, because it might throw an EOutOfMemory
exception even if there is almost half of the memory still available.
Is there any way to influence this behaviour? How do other collection classes deal with this scenario?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要了解字典的工作原理。字典包含一个“哈希桶”列表,其中放置您插入的项目。这是一个有限的数字,所以一旦你填满它,你就需要分配更多的桶,这是没有办法解决的。由于对象到存储桶的分配是基于哈希函数的结果,因此您不能简单地将存储桶添加到数组的末尾并将内容放入其中,您需要重新分配整个块列表,重新散列所有内容并将其放入(新的)相应的存储桶中。
鉴于这种行为,使字典在满后不重新分配的唯一方法是确保它永远不会满。如果您知道要在字典中插入的项目数,请将其作为参数传递给构造函数,这样就完成了,不再需要重新分配字典。
如果您无法做到这一点(您不知道字典中的项目数量),您需要重新考虑是什么让您首先选择了
TDictionary
并选择为您的特定算法提供更好折衷的数据结构。例如,您可以使用二叉搜索树,因为它们通过轮换现有节点中的信息来实现平衡,永远不需要重新分配。You need to understand how a Dictionary works. A dictionary contains a list of "hash buckets" where the items you insert are placed. That's a finite number, so once you fill it up you need to allocate more buckets, there's no way around it. Since the assignment of objects-to-buckets is based on the result of a hash function, you can't simply add buckets to the end of the array and put stuff in there, you need to re-allocate the whole list of blocks, re-hash everything and put it in the (new) corresponding buckets.
Given this behavior, the only way to make the dictionary not re-allocate once full is to make sure it never gets full. If you know the number of items you'll insert in the dictionary pass it as a parameter to the constructor and you'll be done, no more dictionary reallocations.
If you can't do that (you don't know the number of items you'll have in the dictionary) you'll need to reconsider what made you select the
TDictionary
in the first place and select a data structure that offers better compromise for your particular algorithm. For example you could use binary search trees, as they do the balancing by rotating information in existing nodes, no need for re-allocations ever.