Is It Possible to Use Hashcodes as a Bitmask to Efficiently Store/Track Collection Membership?

冷暖自知 提交于 2019-12-12 03:48:48

问题


Currently I have a solution where I keep track of objects I am interested in by getting their hashcode via Object.GetHashCode and then storing them in a HashSet<int>.

However, I have also been learning about bitmasks and bitwise operations and I am quite intrigued by them. Here is a great question that I found close to what I am looking to do. However, I cannot seem to make this work efficiently for hash codes.

There is also this question, but it seems to deal with 5-bit numbers, when hash codes are int's (32-bits).

I do get the BitArray solution (from the first referenced question) working, but it is not as fast as my current HashSet approach is. This is due to the sheer number of items in the BitArray that need to be created to account for all known hash codes (int.MaxValue).

Is there some a bitmask/bitwise operation I should consider in making this work with a BitArray? Or have I totally gone off the beaten path here and should simply stick with my HashSet<int> solution?


回答1:


This was indeed an instance of going off the beaten path, paired with a misunderstanding of references/memory management. In my case I was using a Dictionary<TKey, TValue> object to store cached results from method calls on an instance. I couldn't use a ConditionalWeakTable because there are at least three parts to a key:

  1. The instance that contains the method where the results are being cached.
  2. Said method.
  3. Arguments being passed into the method.

If I used a ConditionalWeakTable I would have to create "yet another object" (class) that would require yet another allocation, but worse yet would not be referenced by anything (besides the ConditionalWeakTable) and would get garbage collected on the first pass (this is indeed related to another open -- but now also solved -- question of mine).

After much thought around this, I have realized that the answer does indeed lie in ConditionalWeakTable. Rather than use the 3 items above as a key, the answer is to use a Delegate made up from parts 1 and 2, and then pair a Dictionary to that.

Or to put as a field initialization:

readonly ConditionalWeakTable<Delegate, Dictionary<object[], object>> cache = new ConditionalWeakTable<Delegate, Dictionary<object[], object>>();

(Also of note is the use of a StructuralEqualityComparer with the above dictionary to make this work).

This of course does everything I want. It will keep track of objects until the referenced object which contains the method (and from which the Delegate is comprised) is cleaned from memory. At this point, the cached dictionary will also be released as well, clearing out all of its contents.



来源:https://stackoverflow.com/questions/37929406/is-it-possible-to-use-hashcodes-as-a-bitmask-to-efficiently-store-track-collecti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!