- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我的问题可能重复Default implementation for Object.GetHashCode()但我又问了一遍,因为我不明白那个问题的公认答案。
首先,我有三个关于 accepted answer to the previous question 的问题, 其中引用 some documentation如下:
"However, because this index can be reused after the object is reclaimed during garbage collection, it is possible to obtain the same hash code for two different objects."
这是真的吗?在我看来,两个对象不会有相同的哈希码,因为直到对象被垃圾回收(即不再存在)之前,对象的代码不会被重用。
"Also, two objects that represent the same value have the same hash code only if they are the exact same object."
这是个问题吗?例如,我想将一些数据与 DOM 树中的每个节点实例相关联。为此,“节点”必须具有标识或哈希码,以便我可以将它们用作数据字典中的键。我想要的不是一个哈希码来标识它是否是“完全相同的对象”,即“引用相等而不是”值相等)吗?
"This implementation is not particularly useful for hashing; therefore, derived classes should override GetHashCode"
这是真的吗?如果它不利于散列,那么它有什么用呢?为什么它甚至被定义为 Object 的方法?
我的最后一个(也许对我来说最重要的)问题是,如果我必须为具有“引用相等”语义的任意类型发明/覆盖 GetHashCode() 实现,那么以下是一个合理且良好的实现:
class SomeType
{
//create a new value for each instance
static int s_allocated = 0;
//value associated with this instance
int m_allocated;
//more instance data
... plus other data members ...
//constructor
SomeType()
{
allocated = ++s_allocated;
}
//override GetHashCode
public override int GetHashCode()
{
return m_allocated;
}
}
编辑
仅供引用,我使用以下代码对其进行了测试:
class TestGetHash
{
//default implementation
class First
{
int m_x;
}
//my implementation
class Second
{
static int s_allocated = 0;
int m_allocated;
int m_x;
public Second()
{
m_allocated = ++s_allocated;
}
public override int GetHashCode()
{
return m_allocated;
}
}
//stupid worst-case implementation
class Third
{
int m_x;
public override int GetHashCode()
{
return 0;
}
}
internal static void test()
{
testT<First>(100, 1000);
testT<First>(1000, 100);
testT<Second>(100, 1000);
testT<Second>(1000, 100);
testT<Third>(100, 100);
testT<Third>(1000, 10);
}
static void testT<T>(int objects, int iterations)
where T : new()
{
System.Diagnostics.Stopwatch stopWatch =
System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < iterations; ++i)
{
Dictionary<T, object> dictionary = new Dictionary<T, object>();
for (int j = 0; j < objects; ++j)
{
T t = new T();
dictionary.Add(t, null);
}
for (int k = 0; k < 100; ++k)
{
foreach (T t in dictionary.Keys)
{
object o = dictionary[t];
}
}
}
stopWatch.Stop();
string stopwatchMessage = string.Format(
"Stopwatch: {0} type, {1} objects, {2} iterations, {3} msec",
typeof(T).Name, objects, iterations,
stopWatch.ElapsedMilliseconds);
System.Console.WriteLine(stopwatchMessage);
}
}
在我的机器上,结果/输出如下:
First type, 100 objects, 1000 iterations, 2072 msec
First type, 1000 objects, 100 iterations, 2098 msec
Second type, 100 objects, 1000 iterations, 1300 msec
Second type, 1000 objects, 100 iterations, 1319 msec
Third type, 100 objects, 100 iterations, 1487 msec
Third type, 1000 objects, 10 iterations, 13754 msec
我的实现只用了默认实现的一半时间(但我的类型比我的 m_allocated 数据成员大)。
我的实现和默认实现都是线性扩展的。
相比之下,作为健全性检查,愚蠢的实现一开始就很糟糕,而且扩展性更差。
最佳答案
哈希码实现必须具备的最重要的属性是:
如果两个对象比较相等,则它们必须具有相同的哈希码。
如果您有一个类,其中类的实例通过引用比较相等,那么您不需要覆盖 GetHashCode;默认实现保证相同引用的两个对象具有相同的哈希码。 (您在同一个对象上两次调用同一个方法,所以结果当然是一样的。)
如果您编写了一个类,该类实现了与引用相等性不同的自身相等性,那么您需要重写 GetHashCode,以便比较为相等的两个对象具有相等的哈希码。
现在,您只需每次都返回零即可。那将是一个糟糕的散列函数,但它是合法的。
好的散列函数的其他属性是:
GetHashCode 不应该抛出异常
比较其可变状态的相等性并因此对其可变状态进行散列的可变对象非常容易出错。您可以将一个对象放入哈希表中,对其进行变异,并且无法再次将其取出。尽量不要散列或比较可变状态的相等性。
GetHashCode 应该非常快——请记住,好的哈希算法的目的是提高查找性能。如果散列很慢,则无法快速进行查找。
比较不相等的对象应该有不同的散列码,均匀分布在 32 位整数的整个范围内
关于c# - 对象.GetHashCode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1139767/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!