《C#高效编程》读书笔记07-理解GetHashCode()的陷阱
GetHashCode()函数仅会在一个地方用到,即为基于散列(hash)的集合定义的散列键时,此类集合包括HashSet和Dictionary<K,V>容器等。
但object基类提供的GetHashCode()实现有很多问题。
- 对于引用类型,虽然可以正常工作,但效率很低
- 对于值类型,基类中的实现有时甚至是不正确的
如果我们定义的类型不会在容器中作为键来使用,那就没有什么问题。但如果创建的类型将被当做散列表中的键使用,那么就需要自己实现GetHashCode()。
重载GetHashCode()必须遵循以下规则:
- 如果两个对象相对(由operator==定义),那么它们必须生成相同的散列码。否则,这样的散列码将无法用来查找容器中的对象。
- 对于任何一个对象A,A.GetHashCode()必须保持不变。不管在A上调用什么方法,A.GetHashCode()都必然总是返回同一个值。这可以确保放在“桶”中的对象总是位于正确的“桶”中。
- 对于所有的输入,散列函数应该在所有整数中按照随机分布生成散列码。这样散列容器才能得到足够的效率提升。
Object.GetHashCode()使用System.Object中的一个内部字段来产生序列值。系统创建的每一个对象在创建时都会被指派给一个唯一的对象键(一个整数值)。这些键从1开始,每创建一个任意类型的新对象,键值都会随之增长。对象标识字段会在System.Object构造函数中设置,并且之后不能更改。对于一个指定的对象,Object.GetHashCode()会返回该值作为散列码。
但其实Object.GetHashCode()并不满足第三条规则,一个递增序列在所有整数范围内显然不是一个随机分布。Object.GetHashCode()返回的散列码会集中在整数范围的低端。这就意味着Object.GetHashCode()的实现虽说是正确的,但效率不够好。
System.VauleType覆写GetHashCode()方法,为所有值类型提供了一个默认实现。默认的实现会返回类型中定义的第一个字段散列码。只有当值类型的第一个字段是只读的情况下,VauleType.GetHashCode()才能正常工作。只有当值类型第一个字段包含的值有着相对随机分布时,VauleType.GetHashCode()才会产生一个比较高效的散列码。
《C#高效编程》读书笔记07-理解GetHashCode()的陷阱的更多相关文章
- CSAPP 并发编程读书笔记
CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...
- 《深入了解java虚拟机》高效并发读书笔记——Java内存模型,线程,线程安全 与锁优化
<深入了解java虚拟机>高效并发读书笔记--Java内存模型,线程,线程安全 与锁优化 本文主要参考<深入了解java虚拟机>高效并发章节 关于锁升级,偏向锁,轻量级锁参考& ...
- Node.js高级编程读书笔记Outline
Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...
- python高级编程读书笔记(一)
python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...
- unix环境高级编程-读书笔记与习题解答-第一篇
从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...
- MacTalk·人生元编程 - 读书笔记
简介 <MacTalk·人生元编程>是一本随笔文集,主要内容来自作者的微信公众平台"MacTalk By 池建强".本书撰写于2013年,书中时间线却不止于此.作者以一 ...
- 20150206读书笔记<深入理解计算机系统>
●第一章 C是系统级编程的首选.C++显示支持抽象,属于应用级程序设计语言. 简单例子: 一个典型系统的硬件组成: 存储器的层次结构: 注:存储器层次结构的设计思想是,该层存储器作为下一层存储器的高速 ...
随机推荐
- springMVC绑定json参数之二(2.1)
二.springmvc 接收不同格式的json字符串 1.首先扫盲几个知识点: 这个绑定json参数讲的都是用@RequestBody标签,所以前台必须传json字符串,不能是json对象,但是如果不 ...
- python超大数计算
In [26]: %time a = 6789**100000CPU times: user 0 ns, sys: 0 ns, total: 0 nsWall time: 6.2 µsIn [27]: ...
- IO系列之File
1 File类 1.1 目录列表器 在这里我主要是参考Think in Java的内容从而做的一些总结以及扩展.Java中的IO流的设计应该说是Java中最经典的,最学院式的设计,包括它的整体架构设计 ...
- js刷新页面方法大全(转)
刷新页面实现方式总结(HTML,ASP,JS) 转载 2008-11-13 作者: 我要评论 多种方法实现页面的刷新代码 定时刷新: 1,<script>setTimeout( ...
- [原创]SQL表值函数:把用逗号分隔的字符串转换成表格数据
我们日常开发过程中,非常常见的一种需求,把某一个用逗号或者/或者其他符号作为间隔的字符串分隔成一张表数据. 在前面我们介绍了 [原创]SQL 把表中字段存储的逗号隔开内容转换成列表形式,当然按照这 ...
- Hadoop的namenode和secondnamenode分开部署在不同服务器
一.系统环境: Hadoop 0.20.2.JDK 1.6.Linux操作系统 二.使用背景 网上关于Hadoop的集群配置,很多情况下,都是把namenode和secondnamenode部署在 ...
- iOS开发,在main thread以外的thread更新UI
如果需要在异步任务(Async Task)中更新UI,若直接设置UI,会导致程序崩溃. 例如,在异步block中去更改UI: NSOperationQueue *queue=[[NSOperation ...
- URAL 2018 The Debut Album (DP)
题意:给出n长度的数列,其实1的连续个数不超过a,2的连续个数不超过b. 析:dp[i][j][k] 表示前 i 个数,以 j 结尾,并且连续了k个长度,要用滚动数组,要不然MLE. 代码如下: #p ...
- 【Qt官方例程学习笔记】Getting Started Programming with Qt Widgets
创建一个QApplication对象,用于管理应用程序资源,它对于任何使用了Qt Widgets的程序都必要的.对于没有使用Qt Widgets 的GUI应用,可以使用QGuiApplication代 ...
- 20169219《linux内核原理与分析》第七周作业
网易云课堂学习 把write系统调用加入到MenuOS里面 我在试验过程中在MenuOS里加入了time.time-asm.write和write-asm命令.以time和time-asm为例, 步骤 ...