【发布时间】:2009-09-29 20:41:05
【问题描述】:
我正在寻找 HashSet 设计者的头脑。据我所知,我的问题同时适用于 Java 和 C# HashSet,这让我觉得这一定是有充分理由的,尽管我自己也想不出来。
我在HashSet中插入了一个item后,为什么不枚举就无法检索到那个item,几乎不是一个高效的操作?特别是因为 HashSet 是以一种支持高效检索的方式显式构建的。
让 Remove(x) 和 Contains(x) 返回被删除或包含的实际项目通常对我很有用。这不一定是我传递给 Remove(x) 或 Contains(x) 函数的项目。当然,我想我可以通过 HashMap 实现相同的效果,但是当完全可以使用集合来实现这一点时,为什么还要浪费所有的空间和精力呢?
我理解可能存在一些设计问题,即添加此功能将允许使用与其在框架中的角色或未来角色不一致的 HashSet,但如果是这样,这些设计问题是什么?
编辑
要回答更多问题,这里有更多详细信息:
我在 C# 中使用具有覆盖哈希码、equals 等的不可变引用类型来模拟值类型。假设该类型具有成员 A、B 和 C。Hashcode、equals 等仅取决于 A 和 B。给定一些 A 和 B,我希望能够从哈希集中检索该等价项并得到它的 C。我赢了似乎无法为此使用 HashSet,但我至少想知道这是否有任何充分的理由。伪代码如下:
public sealed class X{
object A;
object B;
object extra;
public int HashCode(){
return A.hashCode() + B.hashCode();
}
public bool Equals(X obj){
return obj.A == A && obj.B == B;
}
}
hashset.insert(new X(1,2, extra1));
hashset.contains(new X(1,2)); //returns true, but I can't retrieve extra
【问题讨论】:
-
“为什么没有枚举就无法检索该项目”你能澄清一下你的意思吗,你的意思是 get(),contains() 在你的情况下是 O(n) 吗?
-
当然 :) 我的意思是如果没有枚举,我无法检索到我放入集合中的确切引用。 HashSet 没有 get() 运算符,并且 contains() 接受一个参数,该参数的计算结果可能等于您输入的引用,但可能不是您输入的确切引用。希望可以清除它。
-
在这种情况下,您可以将 equals() 实现为 return this == obj - 即仅检查相同的参考。如果没有对象创建控制,这是要付出高昂的代价。对象创建控制可以单独解决问题。
-
您错过了哈希不一定是唯一的。它只是和索引工具。
-
这至少添加到 .NET (v4.7.2)。