让我们拥有这个C#类(在Java中几乎相同)
public class MyClass {
public string A {get; set;}
public string B {get; set;}
public override bool Equals(object obj) {
var item = obj as MyClass;
if (item == null || this.A == null || item.A == null)
{
return false;
}
return this.A.equals(item.A);
}
public override int GetHashCode() {
return A != null ? A.GetHashCode() : 0;
}
}
如您所见,两个实例的相等性仅MyClass
取决于A
。因此,可以存在两个相等的实例,但它们的B
属性持有不同的信息。
在多种语言(当然包括C#和Java)的标准集合库中,有一个Set
(HashSet
在C#中),该集合可以容纳每组相等的实例中的最多一项。
可以添加项目,删除项目并检查集合中是否包含项目。但是,为什么不可能从集合中获得特定的物品呢?
HashSet<MyClass> mset = new HashSet<MyClass>();
mset.Add(new MyClass {A = "Hello", B = "Bye"});
//I can do this
if (mset.Contains(new MyClass {A = "Hello", B = "See you"})) {
//something
}
//But I cannot do this, because Get does not exist!!!
MyClass item = mset.Get(new MyClass {A = "Hello", B = "See you"});
Console.WriteLine(item.B); //should print Bye
检索我的物品的唯一方法是遍历整个集合并检查所有物品是否相等。但是,这需要O(n)
时间而不是O(1)
!
到目前为止,我还没有发现任何支持get的语言。我所知道的所有“通用”语言(Java,C#,Python,Scala,Haskell ...)似乎都是以相同的方式设计的:可以添加项目,但不能检索它们。是否有充分的理由为什么所有这些语言都不支持某些简单且显然有用的语言?他们不可能全都错,对吗?是否有任何语言支持它?也许从集合中取出特定项目是错误的,但是为什么呢?
有一些相关的SO问题:
/programming/7283338/getting-an-element-from-a-set
/programming/7760364/how-to-retrieve-actual-item-from-hashsett
Set<E>
实现都Map<E,Boolean>
在内部。
a == b
万一破坏了反射性(始终为真)this.A == null
。该if (item == null || this.A == null || item.A == null)
测试是“过头”,并检查多,可能为了创建人为“高质量”的代码。我看到这种“过度检查”,并且在代码审查中一直过分正确。
std::set
支持对象检索,因此并非所有“通用”语言都像您描述的那样。