Hash-consing包含在内存中保留给定对象的一个副本;也就是说,如果两个对象在语义上相同(相同的内容),那么它们应该在物理上相同(存储器中的相同位置)。该技术通常通过保持全局哈希集并仅在不等于哈希集中的对象时创建新对象来实现。F#中的哈希链接和.net中的弱哈希表
另一个要求是散列表中的对象应该是可收集的,如果它们没有被散列表以外的任何东西引用;否则表示,散列表应该包含弱引用。
这个问题更复杂的是需要有恒定的时间,因此浅,哈希和平等测试;因此对象具有一个唯一的标识符,当将新对象添加到表中时,该标识符会增加。
我有一个使用System.Collections.Generic.Dictionary<key, node>
的工作实现,其中key
是一个给出节点的浅层摘要(适用于默认散列和相等测试)的元组,并且node
是对象。唯一的问题是Dictionary
保持对节点的强引用!
我可以使用Dictionary
至WeakReference
's,但这不会释放指向悬空引用的密钥。
一些倡导者使用System.Runtime.CompilerServices.ConditionalWeakTable
,但这个类似乎做了相反的事情:它在收集密钥时释放值,而在收集值时需要释放密钥。
一个可以尝试使用System.Runtime.CompilerServices.ConditionalWeakTable<node, node>
,但我需要自定义的散列和平等的测试...和ConditionalWeakTable
是记录不使用GetHashCode()
虚方法,而不是使用默认的散列函数。
因此,我的问题:是否有一些相当于Dictionary
,将保持对值的弱引用,并且当引用变成悬挂时释放密钥?
您是否需要在收集该值时立即释放密钥?或者你能否放松这个要求,并在稍后的某个时间点解锁? – 2013-03-25 14:27:45
我不需要他们立即被释放 - 这只是我不希望他们积累和无用地消耗大量的内存。我想过运行另一个线程来周期性地杀死具有悬挂引用的键,但这看起来很复杂并且容易出现并发错误。 – 2013-03-25 14:34:05
对于它的价值,我也有一个OCaml实现,使用'Weak'模块的哈希表和一个Java实现'WeakHashMap'。 – 2013-03-25 15:32:47