[英]Why would I use a HashSet over a Dictionary?
I'm trying to implement a list of cached paths on a A* algorithm. 我正在尝试在A *算法上实现缓存路径列表。 Currently, the cached paths are stored in a list like this:
目前,缓存的路径存储在如下列表中:
readonly List<CachedPath> _cachedPaths = new List<CachedPath>();
The operations performed over this list are: 在此列表上执行的操作是:
FirstOrDefault to get an element that satisfies certain conditions FirstOrDefault获取满足某些条件的元素
var cached = _cachedPaths.FirstOrDefault(p => p.From == from && p.To == target && p.Actor == self);
Remove and element 删除和元素
_cachedPaths.Remove(cached);
Additions 附加
_cachedPaths.Add(new CachedPath {
From = from,
To = target,
Actor = self,
Result = pb,
Tick = _world.WorldTick
});
NOTE: The class CachedPath has GetHashCode and Equals overriden by just the From, To and Actor, so two instances that have these same attributes have the same hash and equality. 注意:类CachedPath只有From,To和Actor覆盖GetHashCode和Equals,因此具有这些相同属性的两个实例具有相同的散列和相等性。
Given that quick lookups (Contains), insertions and deletions in a 'HashSet' are O(1) (if I'm not mistaken), I considered using a 'HashSet' to do these operations. 鉴于快速查找(包含),'HashSet'中的插入和删除是O(1)(如果我没有弄错),我考虑使用'HashSet'来执行这些操作。 The only problem is the FirstOrDefault, that I had to enumerate the whole collection to get it.
唯一的问题是FirstOrDefault,我必须枚举整个集合才能得到它。
Given this problem, I considered also using a Dictionary indexed by the hash of From, To and Actor: 鉴于此问题,我还考虑使用由From,To和Actor的哈希索引的Dictionary:
Dictionary<int, CachedPath> cachedPath
Once again, if I'm not mistaken, Dictionary also offers O(1) in insertions, deletions, and also retrieval by Key. 再一次,如果我没有弄错的话,Dictionary还提供O(1)插入,删除和Key检索。 This leads me to think that a Dictionary is a HashSet + O(1) element retrieval capabilities.
这使我认为Dictionary是HashSet + O(1)元素检索功能。
Am I missing something? 我错过了什么吗? Is really Dictionary better than HashSet in the sense that it supports more operations?
在它支持更多操作的意义上,字典真的比HashSet好吗?
Thanks in advance. 提前致谢。
Dictionary
is not better than HashSet
, it's just different. Dictionary
也不好过 HashSet
,它只是不同。
HashSet
when you want to store an unordered collection of items, and HashSet
Dictionary
when you want to associate a set of items called "keys" with another collection of items called "values" Dictionary
One could think of a HashSet
as a Dictionary
with no associated values (in fact, HashSet
is sometimes implemented using a Dictionary
behind the scene) but it is not necessary to think about it in this way: thinking of the two as of entirely different things works fine, too. 可以将
HashSet
视为没有关联值的Dictionary
(实际上, HashSet
有时使用场景后面的Dictionary
实现)但是没有必要以这种方式思考它:将两者视为完全不同的东西工作得很好。
In your case you could potentially improve performance by making a dictionary by actor, like this: 在您的情况下,您可以通过按actor创建字典来提高性能,如下所示:
Dictionary<ActorType,List<CachedPath>> _cachedPathsByActor
This way your linear search would quickly choose a sub-list based on an actor, and then search linearly by target: 这样,线性搜索会快速选择基于actor的子列表,然后按目标线性搜索:
var cached = _cachedPathsByActor[self].FirstOrDefault(p => p.From == from && p.To == target);
or by making an equality comparer that considers all three items, and using a Dictionary
with CachedPath
as both keys and values, and that custom IEqualityComparer<T>
as the key comparer: 或者通过创建一个考虑所有三个项目的相等比较器,并使用带有
CachedPath
的Dictionary
作为键和值,并将自定义IEqualityComparer<T>
作为键比较器:
class CachedPathEqualityComparer : IEqualityComparer<CachedPath> {
public bool Equals(CachedPath a, CachedPath b) {
return a.Actor == b.Actor
&& a.From == b.From
&& a.To == b.To;
}
public int GetHashCode(CachedPath p) {
return 31*31*p.Actor.GetHashCode()+31*p.From.GetHashCode()+p.To.GetHashCode();
}
}
...
var _cachedPaths = new Dictionary<CachedPath,CachedPath>(new CachedPathEqualityComparer());
...
CachedPath cached;
if (_cachedPaths.TryGetValue(self, out cached)) {
...
}
However, this approach assumes that there would be at most one item in the dictionary with identical From
, To
, and Actor
. 但是,这种方法假定字典中最多只有一个项目具有相同的
From
, To
和Actor
。
A hashset will not throw an exception when performing an add. 执行添加时,哈希集不会引发异常。 Instead it returns a bool reflecting success of the add.
相反,它返回一个反映add成功的bool。
Also a hashset does not require a keyValue pair. 此外,散列集不需要keyValue对。 I use hashsets to guarantee a collection of unique values.
我使用hashsets来保证一组唯一值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.